Skip to content

Commit

Permalink
📝 Updates Next.js Docs (#1915)
Browse files Browse the repository at this point in the history
  • Loading branch information
JackDevAU committed Jul 16, 2024
1 parent 9f65627 commit 731f796
Show file tree
Hide file tree
Showing 6 changed files with 573 additions and 89 deletions.
271 changes: 271 additions & 0 deletions content/docs/frameworks/next/app-router.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,271 @@
---
title: Next.js App Router
prev: /docs/frameworks/next/overview
---

> ☝️ This guide assumes you are using the [**Next.js app router.**](https://nextjs.org/docs/app)
## Video Guide

<div style="position:relative;padding-top:56.25%;">
<iframe width="560" frameborder="0" allowfullscreen
style="position:absolute;top:0;left:0;width:100%;height:100%;" src="https://www.youtube.com/embed/0oYSzT1DDLg" title="TinaCMS - Setting up Next.js" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share">
</iframe>
</div>

## Installing dependencies

From within your site's directory, run:

```bash
npx @tinacms/cli@latest init
```

This will ask you a few setup questions. When prompted for the **public assets directory**, enter: **public**.

## Updating your build scripts

`tina init` should have updated your `package.json` scripts.

```json
"scripts": {
"dev": "tinacms dev -c \"next dev\"",
"build": "tinacms build && next build",
"start": "tinacms build && next start"
}
```

These should be applied manually if they haven't been set by the CLI.

## Starting TinaCMS

You can start TinaCMS with:

```bash
pnpm dev
```
**We recommend using pnpm.**

With TinaCMS running, navigate to `http://localhost:3000/admin/index.html`.

> ❓ Hint: If you are getting errors when running this command, please see the [Common Errors](/docs/forestry/common-errors) page.
At this point, you should be able to see the Tina admin, select a post, save changes, and see the changes persisted to your local markdown files.

![TinaCMS Admin Screenshot](/img/hugo-tina-admin-screenshot.png)

## TinaCMS Config file

After running the `tina init` command a few files were created to get you started as quick as possible. One of these is the `tina/config.ts` file. This is a required config file that defines all the tina schemas.

It looks like the following:

```ts
import { defineConfig } from "tinacms";

// Your hosting provider likely exposes this as an environment variable
const branch =
process.env.GITHUB_BRANCH ||
process.env.VERCEL_GIT_COMMIT_REF ||
process.env.HEAD ||
"main";

export default defineConfig({
branch,

// Get this from tina.io
clientId: process.env.NEXT_PUBLIC_TINA_CLIENT_ID,
// Get this from tina.io
token: process.env.TINA_TOKEN,

build: {
outputFolder: "admin",
publicFolder: "public",
},
media: {
tina: {
mediaRoot: "",
publicFolder: "public",
},
},
schema: {
collections: [
{
name: "post",
label: "Posts",
path: "content/posts",
fields: [
{
type: "string",
name: "title",
label: "Title",
isTitle: true,
required: true,
},
{
type: "rich-text",
name: "body",
label: "Body",
isBody: true,
},
],
},
],
},
});

```

**For a more detailed overview about the config see [Content Modeling with TinaCMS](docs/extending-tina/overview/)**

> 💡 If you've followed this guide using the `tina init` command, you might have noticed that a `content` and a `pages` folder got created:
>
> ```bash
> Adding file at content/posts/hello-world.md... ✅
> Adding file at pages/demo/blog/[filename].tsx... ✅
> ```
>
> These can be used as a quick reference but are safe to delete.
## Creating a New Post

> 💡 As defined in the `tina/config.ts` file we have 1 collection called `post` which will be picked up by TinaCMS and mapped to what you see in the TinaCMS Admin page.
1.Head over to `/admin/index.html`

2.Click on Posts

3.Click on Create

4.Enter required fields

5.Save

Now, let's go back and check what was created. You will see a `/content` folder with your new post saved as a `.md` file. This path is defined in the `tina/config.ts` files post collection!

```bash
content
└── posts
└── hello-world.md
```

## Rendering the Post Collection

Let's start by creating a `/posts` folder. The page here will list all our posts.

**File:** `app/posts/page.tsx`

```tsx
import PostList from "./client-page";
import { client } from "../../tina/__generated__/client";

export default async function Page() {
const {data} = await client.queries.postConnection();

return (
<>
<h1>Posts</h1>
<div>
{data.postConnection.edges.map((post) => (
<div key={post.node.id}>
<Link href={`/posts/${post.node._sys.filename}`}>
{post.node._sys.filename}
</Link>
</div>
))}
</div>
</>
)
}
```
As you may have noticed this is a Server Rendered page. Depending on how this page is generated can mean Next will either,

- **A. Build this as a Dynamic / Server Rendered page**
- **B. Build this as a Static page.**

This is up to you on how you want this page to be rendered.

## Rendering a Single Post

To make this work with TinaCMS Visual Editor we are going to break this across 2 components. 1 will build the page at build time. The other will be a client rendered page that can interact and work with TinaCMS.

**File:** `app/posts/[...filename].tsx`

```tsx
import Post from "./client-page";
import client from "../../../tina/__generated__/client";

export async function generateStaticParams() {
const pages = await client.queries.postConnection();
const paths = pages.data?.postConnection?.edges?.map((edge) => ({
filename: edge?.node?._sys.breadcrumbs,
}));

return paths || [];
}


export default async function PostPage({
params,
}: {
params: { filename: string[] };
}) {

const data = await client.queries.post({
relativePath: `${params.filename}.md`,
});

return (
<Post {...data}></Post>
);
}
```



Here we are using [generateStaticParams](https://nextjs.org/docs/app/api-reference/functions/generate-static-params) to build these pages as SSG. You are free to change this however you like.

Now to make the Visual Editor work, we will create a new "client page":

**File:** `app/posts/[...filename]/client-page.tsx`

```tsx
"use client"
import { useTina } from "tinacms/dist/react";
import { PostQuery } from "../../../tina/__generated__/types";

interface ClientPageProps {
query: string;
variables: {
relativePath: string;
};
data: PostQuery;
}

export default function Post(props : ClientPageProps) {
// data passes though in production mode and data is updated to the sidebar data in edit-mode
const { data } = useTina({
query: props.query,
variables: props.variables,
data: props.data,
});
return (
<code>
<pre
style={{
backgroundColor: "lightgray",
}}
>
{JSON.stringify(data.post, null, 2)}
</pre>
</code>
);
}
```

## Next Steps

- [Check out the content modeling docs](/docs/schema/)
- [Learn how to query your content](/docs/features/data-fetching/)
- [Deploy Your Site](/docs/tina-cloud)

23 changes: 23 additions & 0 deletions content/docs/frameworks/next/overview.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
---
title: NextJS + TinaCMS Overview
next: /docs/frameworks/next/app-router
---

## Using Next.js? Pick a Guide

- [App Router (⭐ Recommended)](/docs/frameworks/next/app-router/)
- [Pages Router](/docs/frameworks/next/pages-router)

## Setting up Visual Editing (Optional)

If you want to power your pages with TinaCMS's API, you'll be able to leverage TinaCMS's visual editing features.

![Block-based Editing Visual](/gif/blocks.gif)

Read more about [data fetching](/docs/features/data-fetching/) and [visual editing](/docs/contextual-editing/overview/).

## Next Steps

- [Check out the content modeling docs](/docs/schema/)
- [Learn how to query your content](/docs/features/data-fetching/)
- [Deploy Your Site](/docs/tina-cloud)
Loading

0 comments on commit 731f796

Please sign in to comment.