shuding / nextra

Simple, powerful and flexible site generation framework with everything you love from Next.js.
https://nextra.site
MIT License
11.87k stars 1.28k forks source link

Support for app router #2023

Closed jonnylangefeld closed 1 month ago

jonnylangefeld commented 1 year ago

I'm using the next.js app router and Nextra doesn't quite work with that yet.

next.config.mjs:

import nextra from 'nextra'

/**
 * @type {import('next').NextConfig}
 */
const nextConfig = {
  distDir: './.next', // Nextra supports custom `nextConfig.distDir`
  reactStrictMode: true,
  pageExtensions: ["js", "jsx", "ts", "tsx", "mdx"],
  experimental: {
    appDir: true,
    mdxRs: true,
    // once this makes it into a release: https://github.com/vercel/next.js/pull/51755
    //   serverActions: true,
    //   serverActionsBodySizeLimit: '5mb',
  },
}

const withNextra = nextra({
  theme: 'nextra-theme-docs',
  themeConfig: './theme.config.tsx'
})

export default withNextra(nextConfig)

when I run npm run dev:

- error Failed to load next.config.mjs, see more info here https://nextjs.org/docs/messages/next-config-error
Error: > The `app` directory is experimental. To enable, add `appDir: true` to your `next.config.js` configuration under `experimental`. See https://nextjs.org/docs/messages/experimental-app-dir-config
    at findPagesDir (~/project/node_modules/next/dist/lib/find-pages-dir.js:98:19)
    at findPagesDirectory (~/project/node_modules/nextra/dist/index.js:155:15)
    at Object.<anonymous> (~/project/node_modules/nextra/dist/index.js:159:53)
    at Module._compile (node:internal/modules/cjs/loader:1256:14)
    at Module._extensions..js (node:internal/modules/cjs/loader:1310:10)
    at Module.load (node:internal/modules/cjs/loader:1119:32)
    at Module._load (node:internal/modules/cjs/loader:960:12)
    at ModuleWrap.<anonymous> (node:internal/modules/esm/translators:169:29)
    at ModuleJob.run (node:internal/modules/esm/module_job:194:25) {
  type: 'Error'
}
C-EO commented 1 year ago

@jonnylangefeld Nextra only works with the ./pages directory at the moment. Support for the app router has not yet been implemented and might be a v3 feature.

erichosick commented 1 year ago

Similar discussion at Nextra in my already existing NextJs 13 app.

erichosick commented 1 year ago

C-EO mentioned this in another discussion but it may be helpful here too: https://github.com/shuding/nextra/discussions/1142#discussioncomment-4552759.

jakeleboeuf commented 1 year ago

Has there been any progress moving towards the App Router?

dimaMachina commented 1 year ago

@jakeleboeuf there is no progress currently

A disadvantage of the App router for mdx docs is that each mdx page should be inside a folder for example

docs/
  introduction/
    page.mdx

Also, you can't share your layout (nextra-theme) from App router to the Pages router, so you can't have the layout defined in App router and mdx documents stored in /pages folder

jthrilly commented 1 year ago

A disadvantage of the App router for mdx docs is that each mdx page should be inside a folder

Just a note that we addressed this by using a catch-all segment ([...slug}) and dynamically importing and rendering the mdx file based on this slug (in combination with generateStaticParams).

If you do it this way, you don't need the pages directory at all, and so the theme can just use the app directory root layout.

dimaMachina commented 1 year ago

A disadvantage of the App router for mdx docs is that each mdx page should be inside a folder

Just a note that we addressed this by using a catch-all segment ([...slug}) and dynamically importing and rendering the mdx file based on this slug (in combination with generateStaticParams).

If you do it this way, you don't need the pages directory at all, and so the theme can just use the app directory root layout.

Can you share the code or repo where you dynamically import mdx files?

jakeleboeuf commented 1 year ago

If you do it this way, you don't need the pages directory at all, and so the theme can just use the app directory root layout.

@jthrilly how does that work? Did you setup your root Layout in the app dir to render the nextra theme? I'm looking for all the benefits of Nextra without losing all the benefits of the NextJS App Router world (ie RSC and friends).

jthrilly commented 1 year ago

@jthrilly how does that work? Did you setup your root Layout in the app dir to render the nextra theme? I'm looking for all the benefits of Nextra without losing all the benefits of the NextJS App Router world (ie RSC and friends).

We aren't using Nextra currently. We wanted to, but we want app dir support. We built our solution as an experiment in how hard it would be to set up manually.

Can you share the code or repo where you dynamically import mdx files?

Its a pretty simple process:

  1. Use getStaticParams to build a flat map of your docs directory as it is on the filesystem. The result should basically be a collection in the format:
[
  { slug: '/path/to/file.mdx' }
]
  1. Create a page.tsx under a catch-all route segment (for example app/[...slug]/page.tsx). In this page, get the slug from the page params object, and use the value to get the path to the appropriate mdx file.
  2. Read the file from the path using fs and pass the content into your markdown processor (we are using matter: matter(fileContent).
  3. Render the result inside of <MDXRemote> or whatever.
dimaMachina commented 1 year ago

Render the result inside of <MDXRemote> or whatever.

@erichosick In this case you’ll be unable to

  1. use import statements in your mdx files
  2. have ssg in mdx files
  3. you couldn’t use new _meta.jsx/tsx since mdx files are loaded not with nextra/loader
jakeleboeuf commented 1 year ago

We aren't using Nextra currently.

@erichosick gotcha, that setup makes sense if you're just looking to avoid the folder/page.tsx architecture. It's the Nextra + App Router part I'm looking for here, but tbh I'm not sure Nextra is the only thing holding me back at the moment. I need to better understand how mdx fits into the React Server Components world.

For my use case, I'm working on a design system that will ship Server Components, and it would be ideal to render all our components in our Docs along with usage examples without any extra work done on components purely for our docs. But again, I'm not 100% sure this is a Nextra problem or if I'll run into issues no matter where I try to render RSC in .mdx files.

*runs to the react repo 👀

dimaMachina commented 1 year ago

@jakeleboeuf If you want to take a look at app router with MDX I will suggest source code of Rauch's blog

SaadBazaz commented 1 year ago

Can't we just write a codegen/script which converts pagesDir mdx files to page.tsx?

dimaMachina commented 11 months ago

It seems like the only way to support App Router is to render mdx remotely (inspired by Lee blog https://github.com/leerob/leerob.io/blob/bb66498d9fc7dbfa28efcd1eaa475cb36d524efe/app/blog/%5Bslug%5D/page.tsx#L127)

Example of file structure

|- docs
   |- my-page.mdx
   |- my-folder
      |- some-another-page.md
|- app
   |- docs
       |- [[...slug]]
          |- layout.tsx <-- nextra layout
          |- page.tsx <-- catch-all page that renders mdx with https://github.com/hashicorp/next-mdx-remote

That means the following

✅ no need to put each mdx page inside folder with page.mdx name as in https://github.com/rauchg/blog/blob/main/app/(post)/2021/making-the-web-faster/page.mdx ❌ all imports from mdx files will be stripped ⚠️ figure out how to deal with _meta files

tubbo commented 10 months ago

@dimaMachina can you explain a bit more about why app/ can't be supported? is there something fundamentally blocking the project that's a total "showstopper", or is it more about the level of effort? given how much stuff nextra provides that may not be possible (or may require a lot of extra configuration) with server-rendered components, i can totally understand that. moreso just curious as someone who's been following this thread for a while and anticipating a future nextra version that i could use with the app router..

dimaMachina commented 10 months ago

@tubbo putting each mdx page in the folder with page.mdx file feels weird UX for me https://github.com/shuding/nextra/issues/2023#issuecomment-1749804333

solution with next-mdx-remote https://github.com/shuding/nextra/issues/2023#issuecomment-1858999095 doesn't allow import statements and fast-refresh will not work too

both proposals for me are not good enough to replace pages router with for this moment

marcofugaro commented 5 months ago

@dimaMachina could you elaborate on layout.tsx? What do you mean by "nextra layout", what are the contents of that file?

SySagar commented 2 months ago

does it still now support app router?

Shubham-EV commented 1 month ago

does it still now support app router?

Yes check out nextra 4 pre-release.

dimaMachina commented 1 month ago

Nextra v3 was finally released. And Nextra v4 prerelease just out! Currently without docs changes update or migration guide.

Nextra v4 will support a file-based router for your mdx files, for anyone who wants to give it a try, feel free to take a look at nextra.site migration https://github.com/shuding/nextra/tree/v4-v2/docs or blog https://github.com/shuding/nextra/tree/v4-v2/examples/blog

Nextra v4 will also support rendering your docs from a single catch-all route app/[[...slug]].jsx. Currently, as unstable and without hot reloading working, but I will fix it before stable releasing Fixed.

Feel free to take a look at docs and i18n docs examples that were migrated to it! https://github.com/shuding/nextra/tree/v4-v2/examples

Prerelease v4 last versions: https://github.com/shuding/nextra/releases/tag/nextra%404.0.0-app-router.6 https://github.com/shuding/nextra/releases/tag/nextra-theme-docs%404.0.0-app-router.6 https://github.com/shuding/nextra/releases/tag/nextra-theme-blog%404.0.0-app-router.6

Feel free to share your feedback and create separated issues for problems you encountered

Have fun!

I will close this issue to keep track of progress at https://github.com/shuding/nextra/issues/2600