shuding / nextra

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

Possible to augment/extend `nextra-theme-docs`? #459

Open brianjenkins94 opened 2 years ago

brianjenkins94 commented 2 years ago

Given a Next.js application configured with the Nextra plugin like so:

// /next.config.js

module.exports = (require("nextra")({
    "theme": "./layouts/docs"
}))();

This "works":

// /layouts/docs/index.tsx

import nextra from "nextra-theme-docs";

export default function Layout(pageProps) {
    const Nextra = nextra(pageProps, {
        "footerText": "Copyright ©. All rights reserved."
    });

    return Nextra;
}

Would it be possible to do something like this?:

// /layouts/docs/index.tsx

import nextra from "nextra-theme-docs";

export default function Layout(pageProps) {
    const Nextra = nextra(pageProps, {
        "footerText": "Copyright ©. All rights reserved."
    });

    return (
        <>
            <Head>
                <link href="../../node_modules/nextra-theme-docs/style.css" rel="stylesheet" />
            </Head>

            {Nextra}
        </>
    );
}

This would allow me to base my theme off of the out-of-the-box nextra-theme-docs theme but also make changes to the default styling/layout in a convenient way.

I'll see if I can put together a gist.

brianjenkins94 commented 2 years ago

Minimal sample that reproduces the issue (apparently gists can't do folders):

nextra-459.zip (just 10 short files, most of which are boilerplate)

To reproduce the issue:

  1. On a non-Windows machine (Windows file paths break it)

  2. cd nextra-459

  3. npm install

  4. npm run dev

  5. Navigate to http://localhost:3000/docs/test

brianjenkins94 commented 2 years ago

Very nearly got it:

// /layouts/docs/index.tsx

import "nextra-theme-docs/style.css";
import nextra from "nextra-theme-docs";

export default function Layout(pageProps) {
    const Nextra = nextra(pageProps, {
        "head": (
            <>
                <link href="/css/nextra-overrides.css" rel="stylesheet" />
            </>
        ),
        "footerText": "Copyright ©. All rights reserved."
    });

    return Nextra;
}

I just need to sort out my _app.tsx since for some reason NextraPage doesn't have a getLayout on it when it gets to my custom Layout function. (by all appearances it should...)

brianjenkins94 commented 2 years ago

I've gone with this for the time being:

// /pages/_app.tsx

import type { AppProps } from "next/app";
import Layout from "../layouts/default";
import Head from "next/head";

export default function App({ Component, pageProps }: AppProps) {
    if (Component.name === "NextraPage") {
        Component.getLayout = function(page) {
            return Component(page);
        };
    }

    const getLayout = Component["getLayout"] ?? function(page) { return <Layout children={page} />; };

    return (
        <>
            <Head>
                <meta name="viewport" content="width=device-width, initial-scale=1" />
            </Head>

            {getLayout(<Component {...pageProps} />)}
        </>
    );
}

But it would be nice if NextraPage had the getLayout function on it. I'm not actually sure why it doesn't.

pratik9315 commented 2 years ago

Hey! I saw this issue listed on bounty source, is this issue still open to work on?