diff --git a/.prettierignore b/.prettierignore index ba0efe5101..8795b4d5f8 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1 +1 @@ -**/.contentlayer +**/.content-collections diff --git a/apps/web/.gitignore b/apps/web/.gitignore index ef9bed258f..78f775b361 100644 --- a/apps/web/.gitignore +++ b/apps/web/.gitignore @@ -33,8 +33,8 @@ yarn-error.log* # vercel .vercel -# contentlayer -.contentlayer +# content-collections +.content-collections # Sentry Auth Token .sentryclirc diff --git a/apps/web/content-collections.ts b/apps/web/content-collections.ts new file mode 100644 index 0000000000..87f1e8c00a --- /dev/null +++ b/apps/web/content-collections.ts @@ -0,0 +1,165 @@ +import { defineCollection, defineConfig } from "@content-collections/core"; +import { compileMDX } from "@content-collections/mdx"; +import readingTime from "reading-time"; +import rehypeAutolinkHeadings from "rehype-autolink-headings"; +import rehypePrettyCode from "rehype-pretty-code"; +import rehypeSlug from "rehype-slug"; + +const autolinkHeadings = [ + rehypeAutolinkHeadings, + { + behavior: "append", + headingProperties: { + className: "group", + }, + properties: { + className: [ + "no-underline group-hover:after:content-['#'] after:text-muted-foreground/30 after:hover:text-muted-foreground ml-1 after:p-1", + ], + "aria-hidden": "true", + }, + }, +]; + +const prettyCode = [ + rehypePrettyCode, + { + theme: { + dark: "github-dark-dimmed", + light: "github-light", + }, + // biome-ignore lint/suspicious/noExplicitAny: + onVisitLine(node: any) { + // Prevent lines from collapsing in `display: grid` mode, and + // allow empty lines to be copy/pasted + if (node.children.length === 0) { + node.children = [{ type: "text", value: " " }]; + } + }, + // biome-ignore lint/suspicious/noExplicitAny: + onVisitHighlightedLine(node: any) { + node.properties.className.push("highlighted"); + }, + // biome-ignore lint/suspicious/noExplicitAny: + onVisitHighlightedWord(node: any) { + node.properties.className = ["word"]; + }, + }, +]; + +const posts = defineCollection({ + name: "Posts", + directory: "src/content/posts", + include: "**/*.mdx", + schema: (z) => ({ + title: z.string(), + description: z.string(), + image: z.string(), + publishedAt: z.coerce.date(), + author: z.object({ + name: z.string(), + url: z.string().optional(), + avatar: z.string().optional(), + }), + }), + transform: async (document, context) => { + const mdx = await compileMDX(context, document, { + // @ts-expect-error + rehypePlugins: [rehypeSlug, prettyCode, autolinkHeadings], + }); + return { + ...document, + mdx, + slug: document._meta.fileName.replace(/\.mdx$/, ""), + readingTime: readingTime(document.content).text, + }; + }, +}); + +const legals = defineCollection({ + name: "Legals", + directory: "src/content/legal", + include: "**/*.mdx", + schema: (z) => ({ + title: z.string(), + updatedAt: z.string(), + }), + transform: async (document, context) => { + const mdx = await compileMDX(context, document, { + // @ts-expect-error + rehypePlugins: [rehypeSlug, prettyCode, autolinkHeadings], + }); + return { + ...document, + mdx, + slug: document._meta.fileName.replace(/\.mdx$/, ""), + }; + }, +}); + +const faqs = defineCollection({ + name: "FAQs", + directory: "src/content/faq", + include: "**/*.mdx", + schema: (z) => ({ + title: z.string(), + order: z.number(), + }), + transform: async (document, context) => { + const mdx = await compileMDX(context, document, { + // @ts-expect-error + rehypePlugins: [rehypeSlug, prettyCode, autolinkHeadings], + }); + return { + ...document, + mdx, + slug: document._meta.fileName.replace(/\.mdx$/, ""), + }; + }, +}); + +const changelogs = defineCollection({ + name: "Changelogs", + directory: "src/content/changelog", + include: "**/*.mdx", + schema: (z) => ({ + title: z.string(), + description: z.string(), + image: z.string(), + publishedAt: z.coerce.date(), + }), + transform: async (document, context) => { + const mdx = await compileMDX(context, document, { + // @ts-expect-error + rehypePlugins: [rehypeSlug, prettyCode, autolinkHeadings], + }); + return { + ...document, + mdx, + slug: document._meta.fileName.replace(/\.mdx$/, ""), + readingTime: readingTime(document.content).text, + }; + }, +}); + +const unrelateds = defineCollection({ + name: "Unrelateds", + directory: "src/content/unrelated", + include: "**/*.mdx", + schema: () => ({}), + transform: async (document, context) => { + const mdx = await compileMDX(context, document, { + // @ts-expect-error + rehypePlugins: [rehypeSlug, prettyCode, autolinkHeadings], + }); + return { + ...document, + mdx, + slug: document._meta.fileName.replace(/\.mdx$/, ""), + }; + }, +}); + +export default defineConfig({ + collections: [posts, legals, faqs, changelogs, unrelateds], +}); diff --git a/apps/web/contentlayer.config.ts b/apps/web/contentlayer.config.ts deleted file mode 100644 index 36724f7821..0000000000 --- a/apps/web/contentlayer.config.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { makeSource } from "contentlayer/source-files"; -import rehypeSlug from "rehype-slug"; -import remarkGfm from "remark-gfm"; - -import { Changelog } from "./src/contentlayer/documents/changelog"; -import { FAQ } from "./src/contentlayer/documents/faq"; -import { LegalPost } from "./src/contentlayer/documents/legal"; -import { Post } from "./src/contentlayer/documents/post"; -import { Unrelated } from "./src/contentlayer/documents/unrelated"; -import autolinkHeadings from "./src/contentlayer/plugins/autolink-headings"; -import prettyCode from "./src/contentlayer/plugins/pretty-code"; - -export default makeSource({ - contentDirPath: "src/content/", - documentTypes: [Post, LegalPost, Changelog, FAQ, Unrelated], - mdx: { - remarkPlugins: [remarkGfm], - rehypePlugins: [rehypeSlug, prettyCode, autolinkHeadings], - }, -}); diff --git a/apps/web/next.config.js b/apps/web/next.config.js index 7a529d933e..7c493b75a4 100644 --- a/apps/web/next.config.js +++ b/apps/web/next.config.js @@ -1,4 +1,4 @@ -const { withContentlayer } = require("next-contentlayer"); +const { withContentCollections } = require("@content-collections/next"); /** @type {import('next').NextConfig} */ const nextConfig = { @@ -59,7 +59,7 @@ const nextConfig = { const { withSentryConfig } = require("@sentry/nextjs"); module.exports = withSentryConfig( - withContentlayer(nextConfig), + withContentCollections(nextConfig), { // For all available options, see: // https://github.com/getsentry/sentry-webpack-plugin#options diff --git a/apps/web/package.json b/apps/web/package.json index e2fa5fdb61..2a31f612af 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -56,14 +56,12 @@ "clsx": "2.0.0", "cmdk": "1.0.0", "cobe": "0.6.3", - "contentlayer": "0.3.4", "date-fns": "2.30.0", "date-fns-tz": "2.0.0", "lucide-react": "0.279.0", "nanoid": "5.0.7", "next": "14.2.15", "next-auth": "5.0.0-beta.21", - "next-contentlayer": "0.3.4", "next-plausible": "3.12.0", "next-themes": "0.2.1", "nuqs": "1.19.1", @@ -92,6 +90,9 @@ "zod": "3.23.8" }, "devDependencies": { + "@content-collections/core": "^0.7.2", + "@content-collections/mdx": "^0.2.0", + "@content-collections/next": "^0.2.3", "@headlessui/tailwindcss": "0.2.0", "@openstatus/tsconfig": "workspace:*", "@types/node": "20.14.8", diff --git a/apps/web/src/app/(content)/_components/pagination.tsx b/apps/web/src/app/(content)/_components/pagination.tsx index 61cefdd598..746dd6b73e 100644 --- a/apps/web/src/app/(content)/_components/pagination.tsx +++ b/apps/web/src/app/(content)/_components/pagination.tsx @@ -1,4 +1,4 @@ -import type { Changelog } from "contentlayer/generated"; +import type { Changelog } from "content-collections"; import { ChevronLeft, ChevronRight } from "lucide-react"; import Link from "next/link"; diff --git a/apps/web/src/app/(content)/blog/[slug]/page.tsx b/apps/web/src/app/(content)/blog/[slug]/page.tsx index 42a624adc9..080644f63f 100644 --- a/apps/web/src/app/(content)/blog/[slug]/page.tsx +++ b/apps/web/src/app/(content)/blog/[slug]/page.tsx @@ -1,4 +1,4 @@ -import { allPosts } from "contentlayer/generated"; +import { allPosts } from "content-collections"; import type { Metadata } from "next"; import { notFound } from "next/navigation"; @@ -28,7 +28,7 @@ export async function generateMetadata({ if (!post) { return; } - const { title, publishedAt: publishedTime, description, slug, image } = post; + const { title, publishedAt, description, slug, image } = post; return { ...defaultMetadata, @@ -39,7 +39,7 @@ export async function generateMetadata({ title, description, type: "article", - publishedTime, + publishedTime: publishedAt.toISOString(), url: `https://www.openstatus.dev/blog/${slug}`, images: [ { diff --git a/apps/web/src/app/(content)/blog/feed.xml/route.ts b/apps/web/src/app/(content)/blog/feed.xml/route.ts index 75e3d1a2d7..cd6ae36173 100644 --- a/apps/web/src/app/(content)/blog/feed.xml/route.ts +++ b/apps/web/src/app/(content)/blog/feed.xml/route.ts @@ -1,4 +1,4 @@ -import { allPosts } from "contentlayer/generated"; +import { allPosts } from "content-collections"; import RSS from "rss"; export async function GET() { diff --git a/apps/web/src/app/(content)/blog/page.tsx b/apps/web/src/app/(content)/blog/page.tsx index b23d733b62..a7febe373d 100644 --- a/apps/web/src/app/(content)/blog/page.tsx +++ b/apps/web/src/app/(content)/blog/page.tsx @@ -11,7 +11,7 @@ import { PaginationContent, PaginationLink, } from "@openstatus/ui"; -import { allPosts } from "contentlayer/generated"; +import { allPosts } from "content-collections"; import { Rss } from "lucide-react"; import type { Metadata } from "next"; import Link from "next/link"; diff --git a/apps/web/src/app/(content)/blog/search-params.ts b/apps/web/src/app/(content)/blog/search-params.ts index 41fce7aa96..d47bfc315a 100644 --- a/apps/web/src/app/(content)/blog/search-params.ts +++ b/apps/web/src/app/(content)/blog/search-params.ts @@ -1,4 +1,4 @@ -import { allPosts } from "contentlayer/generated"; +import { allPosts } from "content-collections"; import { createParser, createSearchParamsCache, diff --git a/apps/web/src/app/(content)/changelog/[slug]/page.tsx b/apps/web/src/app/(content)/changelog/[slug]/page.tsx index 6a6fa824f8..da3728726d 100644 --- a/apps/web/src/app/(content)/changelog/[slug]/page.tsx +++ b/apps/web/src/app/(content)/changelog/[slug]/page.tsx @@ -1,4 +1,4 @@ -import { allChangelogs } from "contentlayer/generated"; +import { allChangelogs } from "content-collections"; import type { Metadata } from "next"; import { notFound } from "next/navigation"; @@ -32,7 +32,7 @@ export async function generateMetadata({ return; } - const { title, publishedAt: publishedTime, description, slug, image } = post; + const { title, publishedAt, description, slug, image } = post; return { ...defaultMetadata, @@ -43,7 +43,7 @@ export async function generateMetadata({ title, description, type: "article", - publishedTime, + publishedTime: publishedAt.toISOString(), url: `https://www.openstatus.dev/changelog/${slug}`, images: [ { diff --git a/apps/web/src/app/(content)/changelog/feed.xml/route.ts b/apps/web/src/app/(content)/changelog/feed.xml/route.ts index c00117c6c6..fd2a6fdac7 100644 --- a/apps/web/src/app/(content)/changelog/feed.xml/route.ts +++ b/apps/web/src/app/(content)/changelog/feed.xml/route.ts @@ -1,4 +1,4 @@ -import { allChangelogs } from "contentlayer/generated"; +import { allChangelogs } from "content-collections"; import RSS from "rss"; export async function GET() { diff --git a/apps/web/src/app/(content)/changelog/page.tsx b/apps/web/src/app/(content)/changelog/page.tsx index 881a7c0d1f..cde250ab90 100644 --- a/apps/web/src/app/(content)/changelog/page.tsx +++ b/apps/web/src/app/(content)/changelog/page.tsx @@ -12,7 +12,7 @@ import { PaginationContent, PaginationLink, } from "@openstatus/ui"; -import { allChangelogs } from "contentlayer/generated"; +import { allChangelogs } from "content-collections"; import { Rss } from "lucide-react"; import type { Metadata } from "next"; import { @@ -70,7 +70,7 @@ export default function ChangelogClient({ title={changelog.title} href={`./changelog/${changelog.slug}`} > - + ))}
diff --git a/apps/web/src/app/(content)/changelog/search-params.ts b/apps/web/src/app/(content)/changelog/search-params.ts index 13821434bf..9dea880b41 100644 --- a/apps/web/src/app/(content)/changelog/search-params.ts +++ b/apps/web/src/app/(content)/changelog/search-params.ts @@ -1,4 +1,4 @@ -import { allChangelogs } from "contentlayer/generated"; +import { allChangelogs } from "content-collections"; import { createParser, createSearchParamsCache, diff --git a/apps/web/src/app/(content)/features/monitoring/page.tsx b/apps/web/src/app/(content)/features/monitoring/page.tsx index e26d848795..d99a71d5f1 100644 --- a/apps/web/src/app/(content)/features/monitoring/page.tsx +++ b/apps/web/src/app/(content)/features/monitoring/page.tsx @@ -12,7 +12,7 @@ import { flyRegions } from "@openstatus/db/src/schema/constants"; import type { Region } from "@openstatus/tinybird"; import { Button } from "@openstatus/ui/src/components/button"; import { Skeleton } from "@openstatus/ui/src/components/skeleton"; -import { allUnrelateds } from "contentlayer/generated"; +import { allUnrelateds } from "content-collections"; import type { Metadata } from "next"; import Link from "next/link"; import { Suspense } from "react"; @@ -129,7 +129,7 @@ export default function FeaturePage() { component={ code ? ( ) : ( diff --git a/apps/web/src/app/about/page.tsx b/apps/web/src/app/about/page.tsx index 1ae6dd1bc4..a4cb2a49ff 100644 --- a/apps/web/src/app/about/page.tsx +++ b/apps/web/src/app/about/page.tsx @@ -1,4 +1,4 @@ -import { allUnrelateds } from "contentlayer/generated"; +import { allUnrelateds } from "content-collections"; import { Separator } from "@openstatus/ui/src/components/separator"; @@ -37,7 +37,7 @@ export default function AboutPage() { {story ? ( ) : null} diff --git a/apps/web/src/app/api/trpc/edge/[trpc]/route.ts b/apps/web/src/app/api/trpc/edge/[trpc]/route.ts index 7ea233718b..2c1fc52855 100644 --- a/apps/web/src/app/api/trpc/edge/[trpc]/route.ts +++ b/apps/web/src/app/api/trpc/edge/[trpc]/route.ts @@ -11,7 +11,6 @@ const handler = (req: NextRequest) => endpoint: "/api/trpc/edge", router: edgeRouter, req: req, - // @ts-expect-error createContext: () => createTRPCContext({ req }), onError: ({ error }) => { console.log("Error in tRPC handler (edge)"); diff --git a/apps/web/src/app/api/trpc/lambda/[trpc]/route.ts b/apps/web/src/app/api/trpc/lambda/[trpc]/route.ts index ca0af87f0c..b36568088b 100644 --- a/apps/web/src/app/api/trpc/lambda/[trpc]/route.ts +++ b/apps/web/src/app/api/trpc/lambda/[trpc]/route.ts @@ -12,7 +12,6 @@ const handler = (req: NextRequest) => endpoint: "/api/trpc/lambda", router: lambdaRouter, req: req, - // @ts-expect-error createContext: () => createTRPCContext({ req }), onError: ({ error }) => { console.log("Error in tRPC handler (lambda)"); diff --git a/apps/web/src/app/api/webhook/stripe/route.ts b/apps/web/src/app/api/webhook/stripe/route.ts index e6f613c676..c83dd3876c 100644 --- a/apps/web/src/app/api/webhook/stripe/route.ts +++ b/apps/web/src/app/api/webhook/stripe/route.ts @@ -22,7 +22,6 @@ export async function POST(req: NextRequest) { /** * Forward to tRPC API to handle the webhook event */ - // @ts-expect-error FIXME const ctx = await createTRPCContext({ req }); const caller = lambdaRouter.createCaller(ctx); diff --git a/apps/web/src/app/legal/[slug]/page.tsx b/apps/web/src/app/legal/[slug]/page.tsx index 22203d7ba1..3046beed22 100644 --- a/apps/web/src/app/legal/[slug]/page.tsx +++ b/apps/web/src/app/legal/[slug]/page.tsx @@ -1,4 +1,4 @@ -import { allLegalPosts } from "contentlayer/generated"; +import { allLegals } from "content-collections"; import { notFound } from "next/navigation"; import { Mdx } from "@/components/content/mdx"; @@ -8,13 +8,13 @@ import { BackButton } from "@/components/layout/back-button"; // export const dynamic = "force-static"; export async function generateStaticParams() { - return allLegalPosts.map((post) => ({ + return allLegals.map((post) => ({ slug: post.slug, })); } export default function PostPage({ params }: { params: { slug: string } }) { - const post = allLegalPosts.find((post) => post.slug === params.slug); + const post = allLegals.find((post) => post.slug === params.slug); if (!post) { notFound(); @@ -30,7 +30,7 @@ export default function PostPage({ params }: { params: { slug: string } }) {

{post.title}

- +
diff --git a/apps/web/src/app/sitemap.ts b/apps/web/src/app/sitemap.ts index 3fe3099185..bb9f1ccede 100644 --- a/apps/web/src/app/sitemap.ts +++ b/apps/web/src/app/sitemap.ts @@ -1,4 +1,4 @@ -import { allChangelogs, allPosts } from "contentlayer/generated"; +import { allChangelogs, allPosts } from "content-collections"; import type { MetadataRoute } from "next"; const addPathToBaseURL = (path: string) => `https://www.openstatus.dev${path}`; diff --git a/apps/web/src/components/content/article.tsx b/apps/web/src/components/content/article.tsx index 83261d03ee..01eecc463d 100644 --- a/apps/web/src/components/content/article.tsx +++ b/apps/web/src/components/content/article.tsx @@ -1,4 +1,4 @@ -import type { Post } from "contentlayer/generated"; +import type { Post } from "content-collections"; import Image from "next/image"; import Link from "next/link"; @@ -41,14 +41,14 @@ export function Article({ post }: { post: Post }) { {post.author.name}

- {formatDate(new Date(post.publishedAt))} + {formatDate(post.publishedAt)} {post.readingTime}

- + ); } diff --git a/apps/web/src/components/content/changelog.tsx b/apps/web/src/components/content/changelog.tsx index b5cf5d2a24..13d3d8e0a3 100644 --- a/apps/web/src/components/content/changelog.tsx +++ b/apps/web/src/components/content/changelog.tsx @@ -1,4 +1,4 @@ -import type { Changelog } from "contentlayer/generated"; +import type { Changelog } from "content-collections"; import Image from "next/image"; import { Mdx } from "@/components/content/mdx"; @@ -21,7 +21,7 @@ export function ChangelogCard({ post }: { post: Changelog }) { /> - + ); } diff --git a/apps/web/src/components/content/mdx-components.tsx b/apps/web/src/components/content/mdx-components.tsx index ae13007ac1..661cd22f69 100644 --- a/apps/web/src/components/content/mdx-components.tsx +++ b/apps/web/src/components/content/mdx-components.tsx @@ -101,5 +101,6 @@ export const components = { td: (props: TdHTMLAttributes) => ( ), + // FIXME: file duplication (not related to content-collections) pre: (props: HTMLAttributes) =>
,
 };
diff --git a/apps/web/src/components/content/mdx.tsx b/apps/web/src/components/content/mdx.tsx
index 82268aa087..81312bf385 100644
--- a/apps/web/src/components/content/mdx.tsx
+++ b/apps/web/src/components/content/mdx.tsx
@@ -1,4 +1,4 @@
-import { getMDXComponent } from "next-contentlayer/hooks";
+import { MDXContent } from "@content-collections/mdx/react";
 
 import { cn } from "@/lib/utils";
 import { components } from "./mdx-components";
@@ -9,8 +9,6 @@ interface MdxProps {
 }
 
 export function Mdx({ code, className }: MdxProps) {
-  const MDXComponent = getMDXComponent(code);
-
   return (
     // FIXME: weird behaviour when `prose-headings:font-cal` and on mouse movement font gets bigger
     
- +
); } diff --git a/apps/web/src/components/content/timeline.tsx b/apps/web/src/components/content/timeline.tsx index 703ff504fc..89174c4dc6 100644 --- a/apps/web/src/components/content/timeline.tsx +++ b/apps/web/src/components/content/timeline.tsx @@ -35,7 +35,7 @@ export function Timeline({ interface ArticleProps { href: string; - publishedAt: string; + publishedAt: Date; imageSrc: string; title: string; children?: React.ReactNode; @@ -53,7 +53,7 @@ function Article({
diff --git a/apps/web/src/components/layout/header/app-header.tsx b/apps/web/src/components/layout/header/app-header.tsx index 295b53c5df..03735c2daa 100644 --- a/apps/web/src/components/layout/header/app-header.tsx +++ b/apps/web/src/components/layout/header/app-header.tsx @@ -1,6 +1,6 @@ "use client"; -import { allChangelogs } from "contentlayer/generated"; +import { allChangelogs } from "content-collections"; import { ArrowUpRight } from "lucide-react"; import Link from "next/link"; diff --git a/apps/web/src/components/marketing/faqs.tsx b/apps/web/src/components/marketing/faqs.tsx index d78950ec2c..4592ff3d22 100644 --- a/apps/web/src/components/marketing/faqs.tsx +++ b/apps/web/src/components/marketing/faqs.tsx @@ -1,6 +1,6 @@ "use client"; -import { allFAQs } from "contentlayer/generated"; +import { allFAQs } from "content-collections"; import { Accordion, @@ -32,10 +32,10 @@ export function FAQs() {
{faqs.map((faq, i) => ( - + {faq.title} - + ))} diff --git a/apps/web/src/components/marketing/lastest-changelogs.tsx b/apps/web/src/components/marketing/lastest-changelogs.tsx index 74082677d5..8bb5943b8c 100644 --- a/apps/web/src/components/marketing/lastest-changelogs.tsx +++ b/apps/web/src/components/marketing/lastest-changelogs.tsx @@ -1,4 +1,4 @@ -import { allChangelogs } from "contentlayer/generated"; +import { allChangelogs } from "content-collections"; import Link from "next/link"; import { Button } from "@openstatus/ui/src/components/button"; diff --git a/apps/web/src/config/pricing-table.tsx b/apps/web/src/config/pricing-table.tsx index 2bc3678dc3..724ba415c5 100644 --- a/apps/web/src/config/pricing-table.tsx +++ b/apps/web/src/config/pricing-table.tsx @@ -2,7 +2,7 @@ import type { LimitsV1, LimitsV2 } from "@openstatus/db/src/schema/plan/schema"; import Link from "next/link"; import type React from "react"; -import { type Changelog, allChangelogs } from "contentlayer/generated"; +import { type Changelog, allChangelogs } from "content-collections"; function renderChangelogDescription(slug: Changelog["slug"]) { const changelog = allChangelogs.find((c) => c.slug === slug); diff --git a/apps/web/src/contentlayer/documents/changelog.ts b/apps/web/src/contentlayer/documents/changelog.ts deleted file mode 100644 index 7774a57ab6..0000000000 --- a/apps/web/src/contentlayer/documents/changelog.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { defineDocumentType } from "contentlayer/source-files"; -import readingTime from "reading-time"; - -export const Changelog = defineDocumentType(() => ({ - name: "Changelog", - contentType: "mdx", - filePathPattern: "changelog/*.mdx", - fields: { - title: { - type: "string", - required: true, - }, - description: { - type: "string", - required: true, - }, - image: { - type: "string", - required: true, - }, - publishedAt: { type: "date", required: true }, - }, - computedFields: { - slug: { - type: "string", - resolve: (post) => post._raw.sourceFileName.replace(/\.mdx$/, ""), - }, - readingTime: { - type: "string", - resolve: (post) => readingTime(post.body.raw).text, - }, - }, -})); diff --git a/apps/web/src/contentlayer/documents/faq.ts b/apps/web/src/contentlayer/documents/faq.ts deleted file mode 100644 index ba5314fe26..0000000000 --- a/apps/web/src/contentlayer/documents/faq.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { defineDocumentType } from "contentlayer/source-files"; - -export const FAQ = defineDocumentType(() => ({ - name: "FAQ", - filePathPattern: "faq/*.mdx", - contentType: "mdx", - fields: { - title: { - type: "string", - required: true, - }, - order: { - type: "number", - required: true, - }, - }, - computedFields: { - slug: { - type: "string", - resolve: (post) => post._raw.sourceFileName.replace(/\.mdx$/, ""), - }, - }, -})); diff --git a/apps/web/src/contentlayer/documents/legal.ts b/apps/web/src/contentlayer/documents/legal.ts deleted file mode 100644 index 05e6885278..0000000000 --- a/apps/web/src/contentlayer/documents/legal.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { defineDocumentType } from "contentlayer/source-files"; - -export const LegalPost = defineDocumentType(() => ({ - name: "LegalPost", - filePathPattern: "legal/*.mdx", - contentType: "mdx", - fields: { - title: { - type: "string", - required: true, - }, - updatedAt: { - type: "string", - required: true, - }, - }, - computedFields: { - slug: { - type: "string", - resolve: (post) => post._raw.sourceFileName.replace(/\.mdx$/, ""), - }, - }, -})); diff --git a/apps/web/src/contentlayer/documents/post.ts b/apps/web/src/contentlayer/documents/post.ts deleted file mode 100644 index 54e1a0c0fa..0000000000 --- a/apps/web/src/contentlayer/documents/post.ts +++ /dev/null @@ -1,50 +0,0 @@ -import { - defineDocumentType, - defineNestedType, -} from "contentlayer/source-files"; -import readingTime from "reading-time"; - -const Author = defineNestedType(() => ({ - name: "Author", - fields: { - name: { type: "string", required: true }, - url: { type: "string" }, - avatar: { type: "string" }, - }, -})); - -export const Post = defineDocumentType(() => ({ - name: "Post", - contentType: "mdx", - filePathPattern: "posts/*.mdx", - fields: { - title: { - type: "string", - required: true, - }, - description: { - type: "string", - required: true, - }, - image: { - type: "string", - required: true, - }, - publishedAt: { type: "date", required: true }, - author: { - type: "nested", // TODO: allow list of authors - of: Author, - required: true, - }, - }, - computedFields: { - slug: { - type: "string", - resolve: (post) => post._raw.sourceFileName.replace(/\.mdx$/, ""), - }, - readingTime: { - type: "string", - resolve: (post) => readingTime(post.body.raw).text, - }, - }, -})); diff --git a/apps/web/src/contentlayer/documents/unrelated.ts b/apps/web/src/contentlayer/documents/unrelated.ts deleted file mode 100644 index c34313d857..0000000000 --- a/apps/web/src/contentlayer/documents/unrelated.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { defineDocumentType } from "contentlayer/source-files"; - -export const Unrelated = defineDocumentType(() => ({ - name: "Unrelated", - filePathPattern: "unrelated/*.mdx", - contentType: "mdx", - fields: {}, - computedFields: { - slug: { - type: "string", - resolve: (post) => post._raw.sourceFileName.replace(/\.mdx$/, ""), - }, - }, -})); diff --git a/apps/web/src/contentlayer/plugins/autolink-headings.ts b/apps/web/src/contentlayer/plugins/autolink-headings.ts deleted file mode 100644 index d1e7807759..0000000000 --- a/apps/web/src/contentlayer/plugins/autolink-headings.ts +++ /dev/null @@ -1,21 +0,0 @@ -import rehypeAutolinkHeadings from "rehype-autolink-headings"; -import type * as unified from "unified"; - -// biome-ignore lint/suspicious/noExplicitAny: -const autolinkHeadings: unified.Pluggable = [ - rehypeAutolinkHeadings, - { - behavior: "append", - headingProperties: { - className: "group", - }, - properties: { - className: [ - "no-underline group-hover:after:content-['#'] after:text-muted-foreground/30 after:hover:text-muted-foreground ml-1 after:p-1", - ], - "aria-hidden": "true", - }, - }, -]; - -export default autolinkHeadings; diff --git a/apps/web/src/contentlayer/plugins/pretty-code.ts b/apps/web/src/contentlayer/plugins/pretty-code.ts deleted file mode 100644 index f096fc5b1b..0000000000 --- a/apps/web/src/contentlayer/plugins/pretty-code.ts +++ /dev/null @@ -1,33 +0,0 @@ -import rehypePrettyCode from "rehype-pretty-code"; -import type * as unified from "unified"; - -// props to https://rehype-pretty-code.netlify.app/ - -// biome-ignore lint/suspicious/noExplicitAny: ContentLayer -const prettyCode: unified.Pluggable = [ - rehypePrettyCode, - { - theme: { - dark: "github-dark-dimmed", - light: "github-light", - }, - // biome-ignore lint/suspicious/noExplicitAny: - onVisitLine(node: any) { - // Prevent lines from collapsing in `display: grid` mode, and - // allow empty lines to be copy/pasted - if (node.children.length === 0) { - node.children = [{ type: "text", value: " " }]; - } - }, - // biome-ignore lint/suspicious/noExplicitAny: ContentLayer - onVisitHighlightedLine(node: any) { - node.properties.className.push("highlighted"); - }, - // biome-ignore lint/suspicious/noExplicitAny: ContentLayer - onVisitHighlightedWord(node: any) { - node.properties.className = ["word"]; - }, - }, -]; - -export default prettyCode; diff --git a/apps/web/tsconfig.json b/apps/web/tsconfig.json index 8bbd69f491..3ae90b5212 100644 --- a/apps/web/tsconfig.json +++ b/apps/web/tsconfig.json @@ -3,7 +3,7 @@ "compilerOptions": { "baseUrl": ".", "paths": { - "contentlayer/generated": ["./.contentlayer/generated"], + "content-collections": ["./.content-collections/generated"], "@/*": ["./src/*"] }, "plugins": [{ "name": "next" }], @@ -15,8 +15,7 @@ "**/*.ts", "**/*.tsx", ".next/types/**/*.ts", - "**/*.mjs", - ".contentlayer/generated" + "**/*.mjs" ], "exclude": ["node_modules", "env.ts"] } diff --git a/biome.jsonc b/biome.jsonc index 20515842e0..5f5b4e693f 100644 --- a/biome.jsonc +++ b/biome.jsonc @@ -26,7 +26,7 @@ "dist", ".wrangler", ".react-email", - ".contentlayer", + ".content-collections", "meta" ] }, @@ -42,7 +42,7 @@ ".nuxt", ".wrangler", ".react-email", - ".contentlayer", + ".content-collections", "meta" ] }, @@ -55,7 +55,7 @@ ".nuxt", ".wrangler", ".react-email", - ".contentlayer" + ".content-collections" ] } } diff --git a/packages/emails/emails/alert.tsx b/packages/emails/emails/alert.tsx index bccfe9dabb..4cf14fda38 100644 --- a/packages/emails/emails/alert.tsx +++ b/packages/emails/emails/alert.tsx @@ -50,9 +50,7 @@ const Alert = ({ data }: { data: z.infer }) => {