diff --git a/.changeset/gentle-clouds-wave.md b/.changeset/gentle-clouds-wave.md new file mode 100644 index 0000000000..84d2eb0b77 --- /dev/null +++ b/.changeset/gentle-clouds-wave.md @@ -0,0 +1,6 @@ +--- +'nextra': patch +'nextra-theme-docs': patch +--- + +polish docs diff --git a/docs/components/features/style.module.css b/docs/components/features/style.module.css index 3d96af4cef..7d466cdd96 100644 --- a/docs/components/features/style.module.css +++ b/docs/components/features/style.module.css @@ -88,17 +88,49 @@ font-feature-settings: initial; } -@media screen and (max-width: 920px) { +.feature :global(.show-on-mobile) { + display: none; +} + +@media screen and (max-width: 1024px) { + .feature { + max-width: 80vw; + width: 100%; + } + .feature.large { + grid-column: span 1; + } .features { - grid-template-columns: repeat(2, 1fr); + grid-template-columns: 1fr; + grid-gap: 3em; + justify-items: center; + } + .feature h3 { + font-size: 28px; + font-size: min(28px, max(4vw, 22px)); + text-align: center; } } @media screen and (max-width: 640px) { + .feature { + max-width: 460px; + width: 100%; + } .feature.large { grid-column: span 1; } .features { grid-template-columns: 1fr; + grid-gap: 3em; + justify-items: center; + } + .feature h3 { + font-size: 34px; + font-size: min(34px, max(4vw, 22px)); + text-align: center; + } + .feature :global(.show-on-mobile) { + display: block; } } diff --git a/docs/next.config.mjs b/docs/next.config.mjs index 4c2071fb4f..d5df9e0369 100644 --- a/docs/next.config.mjs +++ b/docs/next.config.mjs @@ -3,11 +3,11 @@ import nextra from 'nextra' const withNextra = nextra({ theme: 'nextra-theme-docs', themeConfig: './theme.config.tsx', - unstable_staticImage: true, - unstable_flexsearch: { - codeblocks: true + staticImage: true, + flexsearch: { + codeblocks: false }, - unstable_defaultShowCopyCode: true + defaultShowCopyCode: true }) export default withNextra({ diff --git a/docs/package.json b/docs/package.json index de10c122ce..d8e2387291 100644 --- a/docs/package.json +++ b/docs/package.json @@ -12,8 +12,8 @@ "clsx": "^1.2.1", "framer-motion": "^7.3.2", "next": "^13.0.5", - "nextra": "2.0.0-beta.43", - "nextra-theme-docs": "2.0.0-beta.43", + "nextra": "2.0.0-beta.44", + "nextra-theme-docs": "2.0.0-beta.44", "react": "^18.2.0", "react-dom": "^18.2.0" }, diff --git a/docs/pages/about.mdx b/docs/pages/about.mdx index 10b5a0c499..4f6b3287e2 100644 --- a/docs/pages/about.mdx +++ b/docs/pages/about.mdx @@ -1,4 +1,4 @@ -# About +# About Nextra Nextra was initially created by [Vercel](https://vercel.com) members [Shu Ding](https://twitter.com/shuding_) and [Paco Coursey](https://twitter.com/pacocoursey) in 2020. Since 2021, [Yixuan Xu](https://twitter.com/yixuanxu94) contributed tremendously to the project. In 2022, [Dimitri Postolov](https://twitter.com/dimitripost) from [The Guild](https://the-guild.dev) joined the core team to help with the development of 2.0. diff --git a/docs/pages/docs/_meta.json b/docs/pages/docs/_meta.json index 29a9117910..cab75a69e4 100644 --- a/docs/pages/docs/_meta.json +++ b/docs/pages/docs/_meta.json @@ -7,5 +7,13 @@ }, "docs-theme": "Docs Theme", "blog-theme": "Blog Theme", - "custom-theme": "Custom Theme" + "custom-theme": "Custom Theme", + "-- About --": { + "type": "separator", + "title": "More" + }, + "about link": { + "title": "About Nextra", + "href": "/about" + } } diff --git a/docs/pages/docs/blog-theme/start.mdx b/docs/pages/docs/blog-theme/start.mdx index 9e94af2bb0..bd420ddacb 100644 --- a/docs/pages/docs/blog-theme/start.mdx +++ b/docs/pages/docs/blog-theme/start.mdx @@ -80,7 +80,6 @@ export default { ), readMore: 'Read More →', - titleSuffix: null, postFooter: null, darkMode: false, navs: [ diff --git a/docs/pages/docs/docs-theme/start.mdx b/docs/pages/docs/docs-theme/start.mdx index 4831b8827e..9ac6f03669 100644 --- a/docs/pages/docs/docs-theme/start.mdx +++ b/docs/pages/docs/docs-theme/start.mdx @@ -78,7 +78,6 @@ export default { project: { link: 'https://github.com/shuding/nextra', }, - titleSuffix: ' – Nextra', // ... } ``` diff --git a/docs/pages/docs/docs-theme/theme-configuration.mdx b/docs/pages/docs/docs-theme/theme-configuration.mdx index 752db4f929..b43999be5c 100644 --- a/docs/pages/docs/docs-theme/theme-configuration.mdx +++ b/docs/pages/docs/docs-theme/theme-configuration.mdx @@ -10,7 +10,6 @@ export default { link: 'https://github.com/shuding/nextra', }, logo: Project, - titleSuffix: ' – Project', } ``` @@ -40,21 +39,46 @@ export default { Then Nextra will automatically generate the correct file path for all pages. -### Title Suffix +### SEO Options -In Nextra, the website title will be the content of `

` of each page. If `

` is missing, it will use the page title specified in the [page configuration](/docs/docs-theme/page-configuration). You can also provide a global suffix via the `titleSuffix` option. +You can configure SEO related settings via the `useNextSeoProps` option. The `useNextSeoProps` function returns the props that will be passed to the [Next SEO](https://github.com/garmeeh/next-seo#add-seo-to-page) component. + +It is also a hook so you can use APIs like `useRouter` inside to return values conditionally. string)', 'The title suffix.'], + ['useNextSeoProps', '(() => NextSeoProps)', 'A React hook function that returns options for Next SEO.'], ]}/> +For example, we can have all pages rendering the same suffix for ``: + import titleSuffixImage from '../../../public/assets/docs/title-suffix.png' -<Screenshot src={titleSuffixImage} alt="Project link" /> +<Screenshot src={titleSuffixImage} alt="Title suffix" /> ```jsx export default { - titleSuffix: ' – SWR', + useNextSeoProps() { + return { + titleTemplate: '%s – SWR' + } + }, +} +``` + +The `%s` is a [placeholder](https://github.com/garmeeh/next-seo#title-template) that will be replaced by the page title. + +You can also return it conditionally to avoid adding the suffix to the homepage: + +```jsx +export default { + useNextSeoProps() { + const { route } = useRouter() + if (route !== '/') { + return { + titleTemplate: '%s – SWR' + } + } + }, } ``` diff --git a/docs/pages/docs/get-started.mdx.backup b/docs/pages/docs/get-started.mdx.backup index 2a7fd99666..d908713337 100644 --- a/docs/pages/docs/get-started.mdx.backup +++ b/docs/pages/docs/get-started.mdx.backup @@ -34,7 +34,6 @@ module.exports = withNextra() export default { projectLink: 'https://github.com/shuding/nextra', // GitHub link in the navbar docsRepositoryBase: 'https://github.com/shuding/nextra/blob/master', // base URL for the docs repository - titleSuffix: ' – Nextra', nextLinks: true, prevLinks: true, search: true, diff --git a/docs/pages/docs/index.mdx b/docs/pages/docs/index.mdx index 860cfdffca..f4088d0b33 100644 --- a/docs/pages/docs/index.mdx +++ b/docs/pages/docs/index.mdx @@ -20,31 +20,9 @@ To start using Nextra, you need to select a theme first: image arrow title="Blog theme" - href="/docs-theme/installation"> + href="/docs/blog-theme/start"> <>![](/assets/blog-theme.png)</> </Card> </Cards> If you want to use Nextra without a preset theme, or build your own theme, you can follow the [Custom Theme](/docs/custom-theme) docs. - -<div className="hidden"> -## Catalog - -<details> - <summary>What’s the relationship between Next.js, Nextra and Nextra Themes?</summary> - **Next.js** is a general purpose framework for building all kinds of web applications - with React. **Nextra** is a Next.js plugin, which provides a complete solution - around Markdown (MDX) on top of Next.js. A **Nextra Theme** is basically a “layout - component” that determines how a Nextra page is rendered. -</details> - -<details> - <summary>Can I use Nextra in my existing Next.js project?</summary> - Yes, (todo) -</details> - -<details> - <summary>Can I use the docs theme but also create a blog?</summary> - Yes, (todo) -</details> -</div> \ No newline at end of file diff --git a/docs/pages/index.mdx b/docs/pages/index.mdx index 09dd344b83..9a6121add3 100644 --- a/docs/pages/index.mdx +++ b/docs/pages/index.mdx @@ -8,7 +8,6 @@ import { useState } from 'react' import { motion } from "framer-motion" import { Features, Feature } from '@components/features' -import { ThemesAnimation } from '@components/features/themes-animation' import styles from './index.module.css' @@ -49,7 +48,7 @@ export function I18n() { <div className="home-content"> <div className="content-container"> - <h1 className="headline">Make beautiful websites <br className='sm:block hidden'/>with <br className='sm:hidden block'/>Next.js & MDX.</h1> + <h1 className="headline">Make beautiful websites <br className='sm:block hidden'/>with Next.js & MDX.</h1> <p className="subtitle">Simple, powerful and flexible site generation framework <br className='sm:block hidden'/>with everything you love from <a className="nextjs-link" href="https://nextjs.org" target="_blank">Next.js</a>.</p> <p className="subtitle"><Link href="/docs">Start →</Link></p> </div> @@ -100,7 +99,6 @@ export function I18n() { background-size: cover; color: #fff; text-shadow: 0 0 1rem rgba(0,0,0,0.2); - aspect-ratio: 135/86; } :global(.dark #docs-card) { background-image: url(/assets/card-1.dark.png); @@ -121,14 +119,28 @@ export function I18n() { :global(.feat-darkmode h3) { font-size: 48px; } + :global(#search-card) { + display: flex; + flex-direction: column; + justify-content: center; + } + :global(#search-card video) { + position: absolute; + right: 0; + top: 24px; + height: 430px; + pointer-events: none; + max-width: 60%; + } + :global(#fs-card) { + min-height: 240px; + } + :global(#fs-card h3) { + text-align: left; + width: min(300px, 41%); + min-width: 155px; + } @media screen and (max-width: 1200px) { - :global(#docs-card) { - background-position: 0 0; - background-size: 136%; - min-height: 300px; - width: 100%; - aspect-ratio: auto; - } :global(#highlighting-card) { aspect-ratio: auto; } @@ -140,29 +152,80 @@ export function I18n() { letter-spacing: -.08rem; } } + @media screen and (max-width: 1024px) { + :global(#docs-card) { + aspect-ratio: 135/86; + } + :global(#search-card) { + aspect-ratio: 8/3; + } + :global(#search-card h3) { + text-align: left; + } + } + @media screen and (max-width: 768px) { + :global(#docs-card) { + background-position: -26px 0; + background-size: 250%; + min-height: 348px; + width: 100%; + aspect-ratio: auto; + } + } + @media screen and (max-width: 640px) { + :global(#search-card) { + aspect-ratio: 2.5/2; + justify-content: flex-start; + align-items: center; + min-height: 350px; + } + :global(#search-card video) { + top: 43%; + left: 0; + margin: auto; + } + } `}</style> <div className="features-container"> <div className="content-container"> <Features> <Feature large centered id="docs-card"> - <h3>Full-power documentation in minutes.</h3> + <h3>Full-power documentation <br className="show-on-mobile"/>in minutes.</h3> </Feature> - <Feature centered lightOnly style={{ minHeight: 450 }}> - <h3>Pluggable docs, blog, <br/>or custom themes.</h3> - <ThemesAnimation style={{ - position: 'absolute', - left: 0, - bottom: 0, - width: '100%', - }}/> + <Feature centered> + <div className="h-full flex flex-col justify-between"> + <h3>Links and images are <br className="show-on-mobile"/>always <span style={{ fontWeight: 300 }}>optimized</span>.</h3> + <p className='text-left mb-8'>Nextra automatically converts Markdown links and images to use [Next.js Link](https://nextjs.org/docs/routing/introduction#linking-between-pages) and [Next.js Image](https://nextjs.org/docs/basic-features/image-optimization#local-images) when possible. No slow navigation or layout shift.</p> + <div> + <div className={styles.optimization}> + <div style={{ fontSize: '.9rem' }} className="leading-8"> + <code>{`[Learn more](/more)`}</code> + <br/> + <code>{`![Hero](/hero.png)`}</code> + </div> + </div> + <div className="flex justify-center text-neutral-400 my-6"> + <svg xmlns="http://www.w3.org/2000/svg" width="1.2em" viewBox="0 0 20 20" fill="currentColor" className="rotate-90"> + <path fillRule="evenodd" d="M12.293 5.293a1 1 0 011.414 0l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414-1.414L14.586 11H3a1 1 0 110-2h11.586l-2.293-2.293a1 1 0 010-1.414z" clipRule="evenodd" /> + </svg> + </div> + <div className={styles.optimization}> + <div style={{ fontSize: '.9rem' }} className="leading-8"> + <code>{`<Link .../>`}</code> + <br/> + <code>{`<Image .../>`}</code> + </div> + </div> + </div> + </div> </Feature> <Feature id="highlighting-card"> - <h3>Advanced syntax highlighting solution.</h3> + <h3>Advanced syntax <br className="show-on-mobile"/>highlighting solution.</h3> <p>Performant and reliable build-time syntax highlighting powered by [Shiki](https://shiki.matsu.io).</p> </Feature> <Feature> - <h3>I18n as easy as creating new files.</h3> + <h3>I18n as easy as <br className="show-on-mobile"/>creating new files.</h3> <p className='mb-4'>Name your page files with locales suffixed, Nextra and Next.js will do the rest for you.</p> <I18n/> </Feature> @@ -183,7 +246,7 @@ export function I18n() { </svg> <p style={{ textShadow: '0 2px 4px rgb(0 0 0 / 20%)' - }}><a href="https://mdxjs.com/blog/v2" target="_blank" style={{ color: 'currentColor' }}>MDX 2</a> lets you use Components inside Markdown, <br className="hide-medium"/>with huge performance boost since MDX v1.</p> + }}><a href="https://mdxjs.com/blog/v2" target="_blank" style={{ color: 'currentColor' }}>MDX 2</a> lets you use Components inside Markdown, <br className="hide-medium"/>with huge performance boost since v1.</p> </Feature> <Feature centered className="feat-darkmode" style={{ display: 'flex', @@ -241,25 +304,17 @@ export function I18n() { }} >Dark <br/>mode <br/>included.</motion.h3> </Feature> - <Feature large lightOnly style={{ - display: 'flex', - aspectRatio: '8/3', - flexDirection: 'column', - justifyContent: 'center' - }}> - <h3>Full-text search, <br/>zero-config needed.</h3> - <p style={{ maxWidth: 320 }}>Nextra indexes your content automatically at build-time and performs incredibly fast full-text search based on [FlexSearch](https://github.com/nextapps-de/flexsearch).</p> - <video autoPlay="autoplay" loop muted playsInline style={{ - position: 'absolute', - right: 0, - top: 24, - height: 430, - pointerEvents: 'none', - }}> + <Feature large lightOnly id="search-card" > + <div style={{ zIndex: 2}}> + <h3>Full-text search, <br/>zero-config needed.</h3> + <p style={{ maxWidth: 320 }}>Nextra indexes your content automatically at build-time and performs incredibly fast full-text search based on [FlexSearch](https://github.com/nextapps-de/flexsearch).</p> + </div> + <div className="absolute w-full h-full inset-0 hidden sm:block" style={{ background: 'linear-gradient(to right, white 250px, transparent)', zIndex: 1 }}/> + <video autoPlay="autoplay" loop muted playsInline> <source src="/assets/search.mp4" type="video/mp4"/> </video> </Feature> - <Feature large style={{ + <Feature large id="fs-card" style={{ color: 'white', backgroundImage: 'url(/assets/routing.png), url(/assets/gradient-bg.jpeg)', backgroundSize: '140%, 180%', @@ -268,43 +323,30 @@ export function I18n() { textShadow: '0 1px 6px rgb(38 59 82 / 18%)', aspectRatio: '1.765', }}> - <h3 style={{ width: 300 }}>Organize pages intuitively, <br/>with file-system routing from Next.js.</h3> + <h3>Organize pages intuitively, <br/>with file-system routing from Next.js.</h3> </Feature> - <Feature centered> - <div/> - <h3>Links and images are always <span style={{ fontWeight: 300 }}>optimized</span>.</h3> - <p>Nextra converts Markdown link and image to [Next.js Link](https://nextjs.org/docs/routing/introduction#linking-between-pages) and [Next.js Image](https://nextjs.org/docs/basic-features/image-optimization#local-images), keeping your website the best user experience possible.</p> - <div className="mt-6"/> - <div className={styles.optimization}> - <div style={{ fontSize: '.9rem' }} className="leading-8"> - <code>{`[Learn more](/more)`}</code> - <br/> - <code>{`![Hero](/hero.png)`}</code> - </div> - </div> - <div className="flex justify-center text-neutral-400 mt-4"> - <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor" className="w-6 h-6"> - <path strokeLinecap="round" strokeLinejoin="round" d="M19.5 13.5L12 21m0 0l-7.5-7.5M12 21V3" /> - </svg> - </div> - <div className={styles.optimization}> - <div style={{ fontSize: '.9rem' }} className="leading-8"> - <code>{`<Link .../>`}</code> - <br/> - <code>{`<Image .../>`}</code> - </div> - </div> + <Feature className='border border-neutral-400 dark:border-neutral-300' style={{ + backgroundImage: 'url(/assets/high-contrast.png)', + backgroundSize: 750, + backgroundPosition: '-160px 160px', + backgroundRepeat: 'no-repeat', + clipPath: 'none', + borderRadius: '1em', + minHeight: 288 + }}> + <h3>A11y as a top priority.</h3> + <p>Nextra respects system options <br className="show-on-mobile"/>such as <b>Increase Contrast</b> and <b>Reduce Motion</b>.</p> </Feature> <Feature> <h3>Hybrid rendering, <br/>next generation.</h3> - <p>With Nextra, you can leverage the hybrid rendering power from Next.js with your Markdown content including [SSG](https://nextjs.org/docs/basic-features/pages#static-generation-recommended), [SSR](https://nextjs.org/docs/basic-features/pages#server-side-rendering), and [ISR](https://nextjs.org/docs/basic-features/data-fetching/incremental-static-regeneration).</p> + <p>You can leverage the hybrid rendering power from Next.js with your Markdown content including [SSG](https://nextjs.org/docs/basic-features/pages#static-generation-recommended), [SSR](https://nextjs.org/docs/basic-features/pages#server-side-rendering), and [ISR](https://nextjs.org/docs/basic-features/data-fetching/incremental-static-regeneration).</p> </Feature> <Feature large> <h3>And more...</h3> - <p>SEO built-in via [next-seo](https://github.com/garmeeh/next-seo).</p> + <p>SEO / RTL Layout / Plugable Themes / Built-in Components / Last Git Edit Time / Multi-Docs...<br/>A lot of new possibilities to be explored.</p> + <p className="subtitle"><Link className="!no-underline" href="/docs">Start using Nextra →</Link></p> </Feature> </Features> - <p className="subtitle py-8"><Link href="/docs">Start Using Nextra →</Link></p> </div> </div> </div> diff --git a/docs/pages/index.module.css b/docs/pages/index.module.css index fcdbc1eb91..59bfa3c00a 100644 --- a/docs/pages/index.module.css +++ b/docs/pages/index.module.css @@ -26,10 +26,10 @@ .optimization { display: flex; justify-content: center; - margin: 1rem 0 0.25rem; - padding: 1rem; - background: #0e1116; - color: white; + margin: 0; + padding: 1.5rem 1rem; + background: linear-gradient(27deg, #3d3d3d, #000000); + color: #e3e3e3; border-radius: 0.375rem; font-weight: 300; } diff --git a/docs/pnpm-lock.yaml b/docs/pnpm-lock.yaml index ea952f3039..7091e49902 100644 --- a/docs/pnpm-lock.yaml +++ b/docs/pnpm-lock.yaml @@ -9,8 +9,8 @@ importers: clsx: ^1.2.1 framer-motion: ^7.3.2 next: ^13.0.5 - nextra: 2.0.0-beta.43 - nextra-theme-docs: 2.0.0-beta.43 + nextra: 2.0.0-beta.44 + nextra-theme-docs: 2.0.0-beta.44 postcss: ^8.4.19 react: ^18.2.0 react-dom: ^18.2.0 @@ -20,8 +20,8 @@ importers: clsx: 1.2.1 framer-motion: 7.6.15_biqbaboplfbrettd7655fr4n2y next: 13.0.5_biqbaboplfbrettd7655fr4n2y - nextra: 2.0.0-beta.43_7iuvftg57tblwyxclfkwku5xo4 - nextra-theme-docs: 2.0.0-beta.43_7iuvftg57tblwyxclfkwku5xo4 + nextra: 2.0.0-beta.44_7iuvftg57tblwyxclfkwku5xo4 + nextra-theme-docs: 2.0.0-beta.44_7iuvftg57tblwyxclfkwku5xo4 react: 18.2.0 react-dom: 18.2.0_react@18.2.0 devDependencies: @@ -1806,8 +1806,8 @@ packages: - babel-plugin-macros dev: false - /nextra-theme-docs/2.0.0-beta.43_7iuvftg57tblwyxclfkwku5xo4: - resolution: {integrity: sha512-IKg834jpbi7tMISvhNL1eqpT6I/ymgeE/95KNKZJoo++62hIc5W+Pxb2iAHcjlWkjcDTzm0dHVgEYipJNB2w4g==} + /nextra-theme-docs/2.0.0-beta.44_7iuvftg57tblwyxclfkwku5xo4: + resolution: {integrity: sha512-hANacvT74LlnyITWVR9v77BPDItgNLXa0is5tx8G2j83ISJs/U2SjwT6VELSzp0kyozuqQ1NFpRxUPrqLOfrdg==} peerDependencies: next: '>=9.5.3' react: '>=16.13.1' @@ -1832,8 +1832,8 @@ packages: scroll-into-view-if-needed: 2.2.31 dev: false - /nextra/2.0.0-beta.43_7iuvftg57tblwyxclfkwku5xo4: - resolution: {integrity: sha512-wtc0fU4z/dacaW5MSf3ar1jY7Hlij4fqP0PLtoj4F7E0ANV/p+TCU2181S5kCh0TRqMRLCvCpj7lCHZaslPsLA==} + /nextra/2.0.0-beta.44_7iuvftg57tblwyxclfkwku5xo4: + resolution: {integrity: sha512-i5b7rybRUwdKd6Qe5V62QqyYvw0gOl3Js7ZhXgnEaA2mKne1dMwOTzJn4Bc2NTQAuQ63kTfMxOZjfNY4s3p6EA==} peerDependencies: next: '>=9.5.3' react: '>=16.13.1' diff --git a/docs/public/assets/high-contrast.png b/docs/public/assets/high-contrast.png new file mode 100644 index 0000000000..b7fefee696 Binary files /dev/null and b/docs/public/assets/high-contrast.png differ diff --git a/docs/style.css b/docs/style.css index a960f05992..b908ddd84c 100644 --- a/docs/style.css +++ b/docs/style.css @@ -2,6 +2,10 @@ @tailwind components; @tailwind utilities; +body { + font-feature-settings: 'rlig' 1, 'calt' 1; +} + .home-content p { margin-top: 1.5em; line-height: 1.75em; diff --git a/docs/theme.config.tsx b/docs/theme.config.tsx index da6245732f..172c065f1e 100644 --- a/docs/theme.config.tsx +++ b/docs/theme.config.tsx @@ -45,7 +45,7 @@ const config: DocsThemeConfig = { link: 'https://github.com/shuding/nextra' }, docsRepositoryBase: 'https://github.com/shuding/nextra/blob/master', - getNextSeoProps() { + useNextSeoProps() { const { route } = useRouter() if (route !== '/') { return { @@ -60,14 +60,20 @@ const config: DocsThemeConfig = { <meta name="theme-color" content="#ffffff" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta httpEquiv="Content-Language" content="en" /> - <meta name="description" content="Nextra: the Next.js site builder" /> - <meta name="og:description" content="Nextra: the Next.js site builder" /> + <meta + name="description" + content="Make beautiful websites with Next.js & MDX." + /> + <meta + name="og:description" + content="Make beautiful websites with Next.js & MDX." + /> <meta name="twitter:card" content="summary_large_image" /> - <meta name="twitter:image" content="https://nextra.vercel.app/og.png" /> - <meta name="twitter:site:domain" content="nextra.vercel.app" /> - <meta name="twitter:url" content="https://nextra.vercel.app" /> - <meta name="og:title" content="Nextra: Next.js static site generator" /> - <meta name="og:image" content="https://nextra.vercel.app/og.png" /> + <meta name="twitter:image" content="https://nextra.site/og.png" /> + <meta name="twitter:site:domain" content="nextra.site" /> + <meta name="twitter:url" content="https://nextra.site" /> + <meta name="og:title" content="Nextra" /> + <meta name="og:image" content="https://nextra.site/og.png" /> <meta name="apple-mobile-web-app-title" content="Nextra" /> <link rel="icon" href="/favicon.svg" type="image/svg+xml" /> <link rel="icon" href="/favicon.png" type="image/png" /> @@ -103,11 +109,38 @@ const config: DocsThemeConfig = { sidebar: { titleComponent: ({ title, type }) => { if (type === 'separator') { - return <b>{title}!!!!</b> + return <span className="cursor-default">{title}</span> } return <>{title}</> }, defaultMenuCollapseLevel: 0 + }, + footer: { + text: () => { + return ( + <div> + <div className="mb-6 block"> + <a + className="flex items-center gap-1 text-current" + target="_blank" + rel="noopener noreferrer" + title="vercel.com homepage" + href="https://vercel.com?utm_source=nextra.site" + > + <span>Powered by</span> + <svg height={20} viewBox="0 0 283 64" fill="none"> + <title>Vercel + + + + +

© 2022 The Nextra Project.

+ + ) + } } } diff --git a/examples/swr-site/theme.config.tsx b/examples/swr-site/theme.config.tsx index 6df6c5f5e1..25ad74ad16 100644 --- a/examples/swr-site/theme.config.tsx +++ b/examples/swr-site/theme.config.tsx @@ -121,12 +121,6 @@ const config: DocsThemeConfig = { ); }, }, - getNextSeoProps() { - const { locale } = useRouter(); - return { - titleTemplate: `%s | SWR (${locale})`, - }; - }, gitTimestamp: ({ timestamp }) => <>Last updated on {timestamp.toString()}, head() { const config = useConfig(); @@ -218,6 +212,12 @@ const config: DocsThemeConfig = { extraContent: , float: true, }, + useNextSeoProps() { + const { locale } = useRouter(); + return { + titleTemplate: `%s | SWR (${locale})`, + }; + }, }; export default config; diff --git a/packages/nextra-theme-docs/src/components/head.tsx b/packages/nextra-theme-docs/src/components/head.tsx index d7c400e54b..e93ad60935 100644 --- a/packages/nextra-theme-docs/src/components/head.tsx +++ b/packages/nextra-theme-docs/src/components/head.tsx @@ -25,7 +25,7 @@ export function Head(): ReactElement { description={frontMatter.description} canonical={frontMatter.canonical} openGraph={frontMatter.openGraph} - {...config.getNextSeoProps?.()} + {...config.useNextSeoProps?.()} /> {config.faviconGlyph ? ( diff --git a/packages/nextra-theme-docs/src/constants.tsx b/packages/nextra-theme-docs/src/constants.tsx index 6fd5cfe499..7e23449a5d 100644 --- a/packages/nextra-theme-docs/src/constants.tsx +++ b/packages/nextra-theme-docs/src/constants.tsx @@ -50,7 +50,6 @@ export const DEFAULT_THEME: DocsThemeConfig = { component: Footer, text: `MIT ${new Date().getFullYear()} © Nextra.` }, - getNextSeoProps: () => ({ titleTemplate: '%s – Nextra' }), gitTimestamp({ timestamp }) { const { locale = DEFAULT_LOCALE } = useRouter() return ( @@ -151,7 +150,8 @@ export const DEFAULT_THEME: DocsThemeConfig = { component: TOC, float: true, title: 'On This Page' - } + }, + useNextSeoProps: () => ({ titleTemplate: '%s – Nextra' }) } export const DEEP_OBJECT_KEYS = Object.entries(DEFAULT_THEME) diff --git a/packages/nextra-theme-docs/src/types.ts b/packages/nextra-theme-docs/src/types.ts index 53fa29f77c..3c3c36eb95 100644 --- a/packages/nextra-theme-docs/src/types.ts +++ b/packages/nextra-theme-docs/src/types.ts @@ -48,7 +48,6 @@ export interface DocsThemeConfig { component: ReactNode | FC<{ menu: boolean }> text: ReactNode | FC } - getNextSeoProps?: () => NextSeoProps gitTimestamp: ReactNode | FC<{ timestamp: Date }> head: ReactNode | FC i18n: { direction?: string; locale: string; text: string }[] @@ -56,7 +55,7 @@ export interface DocsThemeConfig { logoLink?: boolean | string main?: FC<{ children: ReactNode }> navbar: { - component: ReactNode | FC, + component: ReactNode | FC extraContent?: ReactNode | FC } navigation: @@ -100,7 +99,7 @@ export interface DocsThemeConfig { labels: string } sidebar: { - defaultMenuCollapseLevel: number, + defaultMenuCollapseLevel: number titleComponent: ReactNode | FC<{ title: string; type: string }> } toc: { @@ -109,6 +108,7 @@ export interface DocsThemeConfig { float: boolean title: ReactNode | FC } + useNextSeoProps?: () => NextSeoProps } export type PageTheme = { diff --git a/packages/nextra/src/constants.ts b/packages/nextra/src/constants.ts index 42e297b6b6..eccd46be6b 100644 --- a/packages/nextra/src/constants.ts +++ b/packages/nextra/src/constants.ts @@ -8,6 +8,13 @@ export const LOCALE_REGEX = /\.([a-z]{2}(-[A-Z]{2})?)$/ export const DEFAULT_LOCALE = 'en-US' +export const DEFAULT_CONFIG = { + staticImage: true, + flexsearch: { + codeblocks: true + } +} + export const OFFICIAL_THEMES = [ 'nextra-theme-docs', 'nextra-theme-blog' diff --git a/packages/nextra/src/index.js b/packages/nextra/src/index.js index 33a5f57b05..cc68315e49 100644 --- a/packages/nextra/src/index.js +++ b/packages/nextra/src/index.js @@ -1,6 +1,7 @@ import { NextraPlugin, pageMapCache } from './plugin' import { DEFAULT_LOCALE, + DEFAULT_CONFIG, MARKDOWN_EXTENSION_REGEX, MARKDOWN_EXTENSIONS } from './constants' @@ -9,13 +10,16 @@ const DEFAULT_EXTENSIONS = ['js', 'jsx', 'ts', 'tsx'] const nextra = (...config) => function withNextra(nextConfig = {}) { - const nextraConfig = + const nextraConfig = Object.assign( + {}, + DEFAULT_CONFIG, typeof config[0] === 'string' ? { theme: config[0], themeConfig: config[1] } : config[0] + ) const nextraPlugin = new NextraPlugin(nextraConfig) @@ -40,7 +44,7 @@ const nextra = (...config) => locales: nextConfig.i18n?.locales || [DEFAULT_LOCALE], defaultLocale: nextConfig.i18n?.defaultLocale || DEFAULT_LOCALE, pageMapCache, - newNextLinkBehavior: nextConfig.experimental?.newNextLinkBehavior, + newNextLinkBehavior: nextConfig.experimental?.newNextLinkBehavior } config.module.rules.push(