feat: whyrating - initial project from turbostarter boilerplate
This commit is contained in:
@@ -0,0 +1,86 @@
|
||||
---
|
||||
title: Blog
|
||||
description: Learn how to manage your blog content.
|
||||
url: /docs/web/cms/blog
|
||||
---
|
||||
|
||||
# Blog
|
||||
|
||||
TurboStarter comes with a pre-configured blog implementation that allows you to manage your blog content.
|
||||
|
||||
## Creating a new blog post
|
||||
|
||||
To create a new blog post, you need to create a new directory (its name will be used as the slug of the blog post) with `.mdx` files in the `packages/cms/src/collections/blog/content` directory. Each file in this directory should be named after the locale it belongs to (e.g `en.mdx`, `es.mdx`, etc.).
|
||||
|
||||
The file will start with a [frontmatter](https://mdxjs.com/guides/frontmatter/) block, which is a yaml-like block that contains metadata about the post. The frontmatter block should be surrounded by three dashes (`---`).
|
||||
|
||||
```mdx title="packages/cms/src/collections/blog/content/my-first-blog-post/en.mdx"
|
||||
---
|
||||
title: Quick Tips to Improve Your Skills Right Away
|
||||
description: Whether you're learning a new technical skill or working on personal development, these quick tips can help you improve right away. Learn how to break down your goals, practice consistently, and track your progress using Markdown.
|
||||
publishedAt: 2023-04-19
|
||||
tags: [learning, skills, progress]
|
||||
thumbnail: https://images.unsplash.com/photo-1483639130939-150975af84e5?q=80&w=2370&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D
|
||||
status: published
|
||||
---
|
||||
```
|
||||
|
||||
Let's break down the frontmatter fields:
|
||||
|
||||
* `title`: The title of the blog post (it will be also used to generate a slug for the blog post)
|
||||
* `description`: The description of the blog post
|
||||
* `publishedAt`: The date when the blog post was published
|
||||
* `tags`: The tags of the blog post
|
||||
* `thumbnail`: The thumbnail of the blog post
|
||||
* `status`: The status of the blog post (could be `published` or `draft`)
|
||||
|
||||
After the frontmatter block, you can add the content of the blog post:
|
||||
|
||||
```mdx title="packages/cms/src/collections/blog/content/my-first-blog-post/en.mdx"
|
||||
# Quick Tips to Improve Your Skills Right Away
|
||||
|
||||
Awesome paragraph!
|
||||
|
||||
[Link](https://www.turbostarter.dev)
|
||||
|
||||
<Callout>This is a callout component.</Callout>
|
||||
|
||||
...
|
||||
```
|
||||
|
||||
You can consume the content the same as it's described in [Content Collections](/docs/web/cms/content-collections).
|
||||
|
||||
## BONUS: Using custom components
|
||||
|
||||
As you're using MDX, you can use **any React component** in your blog posts. Just define it as a normal React component and pass it to `<MdxContent />` in `components` prop:
|
||||
|
||||
```tsx title="apps/web/src/app/content/page.tsx"
|
||||
import { MyComponent } from "~/modules/common/my-component";
|
||||
|
||||
export default function Page() {
|
||||
return (
|
||||
<MDXContent
|
||||
code={data.body}
|
||||
components={{ ...defaultMdxComponents, MyComponent }}
|
||||
/>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
Then, you would be able to use it in your document content and it will rendered on the page as a result:
|
||||
|
||||
```mdx title="packages/cms/src/collections/blog/content/my-first-blog-post/en.mdx"
|
||||
...
|
||||
|
||||
# Heading
|
||||
|
||||
Excellent paragraph!
|
||||
|
||||
<MyComponent />
|
||||
|
||||
1. First item
|
||||
2. Second item
|
||||
3. Third item
|
||||
```
|
||||
|
||||
TurboStarter ships with a set of default components that you can use in your blog posts, e.g. `<Callout />`, `<Card />` etc. Use them or define your own to make your blog posts more engaging.
|
||||
@@ -0,0 +1,98 @@
|
||||
---
|
||||
title: Content Collections
|
||||
description: Get started with Content Collections.
|
||||
url: /docs/web/cms/content-collections
|
||||
---
|
||||
|
||||
# Content Collections
|
||||
|
||||
By default, TurboStarter uses [Content Collections](https://www.content-collections.dev/) to store and retrieve content from the MDX files.
|
||||
|
||||
Content from there is used to populate data in the following places:
|
||||
|
||||
* **Blog**
|
||||
* **Legal pages**
|
||||
* **Documentation**
|
||||
|
||||
<Callout title="Why content-collections?">
|
||||
It is a great alternative to headless CMS like Contentful or Prismic based on MDX (a more powerful version of markdown). It is free, open source and the content is located right in your repository.
|
||||
</Callout>
|
||||
|
||||
Of course, you can add more collections and views, as it's very flexible.
|
||||
|
||||
## Defining new collection
|
||||
|
||||
To define a new collection, you need to create a new file in the `packages/cms/src/collections` directory:
|
||||
|
||||
```ts title="packages/cms/src/collections/legal/index.ts"
|
||||
import { defineCollection } from "@content-collections/core";
|
||||
|
||||
export const legal = defineCollection({
|
||||
name: "legal",
|
||||
directory: "src/collections/legal/content",
|
||||
include: "**/*.mdx",
|
||||
schema: (z) => ({
|
||||
title: z.string(),
|
||||
description: z.string(),
|
||||
}),
|
||||
transform: async (doc, context) => {
|
||||
const mdx = await transformMDX(doc, context);
|
||||
|
||||
return {
|
||||
...mdx,
|
||||
slug: doc._meta.directory,
|
||||
locale: doc._meta.fileName.split(".")[0],
|
||||
};
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
Then it's passed to the config in `packages/cms/content-collections.ts` file which is used to generate types and parse content from MDX files.
|
||||
|
||||
```tsx title="packages/cms/content-collections.ts"
|
||||
import { defineConfig } from "@content-collections/core";
|
||||
|
||||
import { legal } from "./src/collections/legal";
|
||||
|
||||
export default defineConfig({
|
||||
collections: [legal],
|
||||
});
|
||||
```
|
||||
|
||||
When you run a development server, content collections will be automatically rebuilt (in `.content-collections` directory) and you will be able to import the content and metadata of each file in your application.
|
||||
|
||||
<Callout title="It's fully type-safe!">
|
||||
By exporting the generated content you get fully type-safe API to interact
|
||||
with the content. We can have type safety on the data that we're receiving
|
||||
from the MDX files.
|
||||
</Callout>
|
||||
|
||||
## Using content collections
|
||||
|
||||
To get some content from `@turbostarter/cms` package, you need to use the exposed API that we described in the [Overview section](/docs/web/cms/overview#api):
|
||||
|
||||
```tsx title="apps/web/src/app/[locale](marketing)/legal/[slug]/page.tsx"
|
||||
import { content } from "@turbostarter/cms";
|
||||
|
||||
export default async function Page({
|
||||
params,
|
||||
}: {
|
||||
params: Promise<{ slug: string; locale: string }>;
|
||||
}) {
|
||||
const item = getContentItemBySlug({
|
||||
collection: CollectionType.LEGAL,
|
||||
slug: (await params).slug,
|
||||
locale: (await params).locale,
|
||||
});
|
||||
|
||||
return <h1>{title}</h1>;
|
||||
}
|
||||
```
|
||||
|
||||
Voila! You can now access the content from the MDX files.
|
||||
|
||||
<Cards>
|
||||
<Card title="Content Collections" description="content-collections.dev" href="https://www.content-collections.dev/" />
|
||||
|
||||
<Card title="MDX" description="mdxjs.com" href="https://mdxjs.com/" />
|
||||
</Cards>
|
||||
@@ -0,0 +1,67 @@
|
||||
---
|
||||
title: Overview
|
||||
description: Manage your content in TurboStarter.
|
||||
url: /docs/web/cms/overview
|
||||
---
|
||||
|
||||
# Overview
|
||||
|
||||
TurboStarter implements a CMS interface that abstracts the implementation from where you store your data. It provides a simple API to interact with your data, and it's easy to extend and customize.
|
||||
|
||||
By default, the starter kit ships with these implementations in place:
|
||||
|
||||
1. [Content Collections](https://www.content-collections.dev/) - a headless CMS that uses [MDX](https://mdxjs.com/) files to store your content.
|
||||
|
||||
The implementation is available under `@turbostarter/cms` package, here we'll go over how to use it.
|
||||
|
||||
## API
|
||||
|
||||
The CMS package provides a simple, unified API to interact with the content. It's the same for all the providers, so you can easily use it with any of the implementations without changing the code.
|
||||
|
||||
### Fetching content items
|
||||
|
||||
To fetch items from your colletions, you can use the `getContentItems` function.
|
||||
|
||||
```ts
|
||||
import { getContentItems } from "@turbostarter/cms";
|
||||
|
||||
const { items, count } = getContentItems({
|
||||
collection: CollectionType.BLOG,
|
||||
tags: [ContentTag.SKILLS],
|
||||
sortBy: "publishedAt",
|
||||
sortOrder: SortOrder.DESCENDING,
|
||||
status: ContentStatus.PUBLISHED,
|
||||
locale: "en",
|
||||
});
|
||||
```
|
||||
|
||||
It accepts an object with the following properties:
|
||||
|
||||
* `collection`: The collection to fetch the items from.
|
||||
* `tags`: The tags to filter the items by.
|
||||
* `sortBy`: The field to sort the items by.
|
||||
* `sortOrder`: The order to sort the items in.
|
||||
* `status`: The status of the items to fetch. It can be `published` or `draft`. By default, only `published` items are fetched.
|
||||
* `locale`: The locale to fetch the items in. By default, all locales are fetched.
|
||||
|
||||
### Fetching a single content item
|
||||
|
||||
To fetch a single content item, you can use the `getContentItemBySlug` function.
|
||||
|
||||
```ts
|
||||
import { getContentItemBySlug } from "@turbostarter/cms";
|
||||
|
||||
const item = getContentItemBySlug({
|
||||
collection: CollectionType.BLOG,
|
||||
slug: "my-first-blog-post",
|
||||
status: ContentStatus.PUBLISHED,
|
||||
locale: "en",
|
||||
});
|
||||
```
|
||||
|
||||
It accepts an object with the following properties:
|
||||
|
||||
* `collection`: The collection to fetch the item from.
|
||||
* `slug`: The slug of the item to fetch.
|
||||
* `status`: The status of the item to fetch. It can be `published` or `draft`. By default, only `published` items are fetched.
|
||||
* `locale`: The locale to fetch the item in. By default, all locales are fetched.
|
||||
Reference in New Issue
Block a user