Add docs (#89)
* Refactor SubscriptionPage and enhance plan management UI - Streamlined SubscriptionPage by consolidating plan handling into FreePlan and ProPlan components for better organization. - Improved UI clarity by directly rendering plan components based on subscription status and enhancing overall user interaction. - Updated button labels for clarity and removed unnecessary components to create a cleaner interface. - Adjusted plan details and descriptions to provide clearer information on subscription benefits and features. * wip
1
docs/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
.next
|
8
docs/mdx-components.js
Normal file
|
@ -0,0 +1,8 @@
|
|||
import { useMDXComponents as getDocsMDXComponents } from 'nextra-theme-docs'
|
||||
|
||||
const docsComponents = getDocsMDXComponents()
|
||||
|
||||
export const useMDXComponents = components => ({
|
||||
...docsComponents,
|
||||
...components
|
||||
})
|
13
docs/next.config.mjs
Normal file
|
@ -0,0 +1,13 @@
|
|||
import nextra from 'nextra'
|
||||
|
||||
const withNextra = nextra({
|
||||
latex: true,
|
||||
search: {
|
||||
codeblocks: false
|
||||
},
|
||||
contentDirBasePath: '/docs'
|
||||
})
|
||||
|
||||
export default withNextra({
|
||||
reactStrictMode: true
|
||||
})
|
6124
docs/package-lock.json
generated
Normal file
22
docs/package.json
Normal file
|
@ -0,0 +1,22 @@
|
|||
{
|
||||
"name": "example-docs",
|
||||
"license": "MIT",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"build": "next build",
|
||||
"dev": "next --turbopack --port 3003",
|
||||
"postbuild": "pagefind --site .next/server/app --output-path public/_pagefind",
|
||||
"start": "next start"
|
||||
},
|
||||
"dependencies": {
|
||||
"@theguild/remark-mermaid": "^0.3.0",
|
||||
"next": "^15.0.2",
|
||||
"nextra": "^4.2.17",
|
||||
"nextra-theme-docs": "^4.2.17",
|
||||
"react": "19.1.0",
|
||||
"react-dom": "19.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"pagefind": "^1.3.0"
|
||||
}
|
||||
}
|
BIN
docs/public/android-icon-192x192.png
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
docs/public/demo.png
Normal file
After Width: | Height: | Size: 378 KiB |
BIN
docs/public/ms-icon-144x144.png
Normal file
After Width: | Height: | Size: 11 KiB |
2
docs/src/app/_ignored/_meta.js
Normal file
|
@ -0,0 +1,2 @@
|
|||
// This file will be NOT treated as `_meta` file, since directory starts with underscore
|
||||
export default {}
|
1
docs/src/app/_ignored/page.mdx
Normal file
|
@ -0,0 +1 @@
|
|||
This file will be NOT treated as page, since directory starts with underscore
|
13
docs/src/app/_meta.js
Normal file
|
@ -0,0 +1,13 @@
|
|||
export default {
|
||||
index: {
|
||||
display: 'hidden'
|
||||
},
|
||||
docs: {
|
||||
type: 'page',
|
||||
title: 'Documentation'
|
||||
},
|
||||
blog: {
|
||||
type: 'page',
|
||||
title: 'Blog'
|
||||
}
|
||||
}
|
BIN
docs/src/app/apple-icon.png
Normal file
After Width: | Height: | Size: 16 KiB |
14
docs/src/app/blog/page.jsx
Normal file
|
@ -0,0 +1,14 @@
|
|||
export default function BlogPage() {
|
||||
return (
|
||||
<h1
|
||||
style={{
|
||||
textAlign: 'center',
|
||||
fontSize: 64,
|
||||
margin: '25vh 0',
|
||||
fontWeight: 'bold'
|
||||
}}
|
||||
>
|
||||
Blog page
|
||||
</h1>
|
||||
)
|
||||
}
|
23
docs/src/app/docs/[[...mdxPath]]/page.jsx
Normal file
|
@ -0,0 +1,23 @@
|
|||
import { generateStaticParamsFor, importPage } from 'nextra/pages'
|
||||
import { useMDXComponents as getMDXComponents } from '../../../../mdx-components'
|
||||
|
||||
export const generateStaticParams = generateStaticParamsFor('mdxPath')
|
||||
|
||||
export async function generateMetadata(props) {
|
||||
const params = await props.params
|
||||
const { metadata } = await importPage(params.mdxPath)
|
||||
return metadata
|
||||
}
|
||||
|
||||
const Wrapper = getMDXComponents().wrapper
|
||||
|
||||
export default async function Page(props) {
|
||||
const params = await props.params
|
||||
const result = await importPage(params.mdxPath)
|
||||
const { default: MDXContent, toc, metadata } = result
|
||||
return (
|
||||
<Wrapper toc={toc} metadata={metadata}>
|
||||
<MDXContent {...props} params={params} />
|
||||
</Wrapper>
|
||||
)
|
||||
}
|
BIN
docs/src/app/favicon.ico
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
docs/src/app/icon.png
Normal file
After Width: | Height: | Size: 6.5 KiB |
59
docs/src/app/layout.jsx
Normal file
|
@ -0,0 +1,59 @@
|
|||
/* eslint-env node */
|
||||
import { Footer, Layout, Navbar } from 'nextra-theme-docs'
|
||||
import { Banner, Head } from 'nextra/components'
|
||||
import { getPageMap } from 'nextra/page-map'
|
||||
import 'nextra-theme-docs/style.css'
|
||||
|
||||
export const metadata = {
|
||||
metadataBase: new URL('https://nextra.site'),
|
||||
title: {
|
||||
template: '%s - Nextra'
|
||||
},
|
||||
description: 'Nextra: the Next.js site builder',
|
||||
applicationName: 'Nextra',
|
||||
generator: 'Next.js',
|
||||
appleWebApp: {
|
||||
title: 'Nextra'
|
||||
},
|
||||
other: {
|
||||
'msapplication-TileImage': '/ms-icon-144x144.png',
|
||||
'msapplication-TileColor': '#fff'
|
||||
},
|
||||
twitter: {
|
||||
site: 'https://nextra.site'
|
||||
}
|
||||
}
|
||||
|
||||
export default async function RootLayout({ children }) {
|
||||
const navbar = (
|
||||
<Navbar
|
||||
logo={
|
||||
<div>
|
||||
<b>Nextra</b>{' '}
|
||||
<span style={{ opacity: '60%' }}>The Next Docs Builder</span>
|
||||
</div>
|
||||
}
|
||||
chatLink="https://discord.gg/hEM84NMkRv"
|
||||
projectLink="https://github.com/goldflag/frogstats"
|
||||
/>
|
||||
)
|
||||
const pageMap = await getPageMap()
|
||||
return (
|
||||
<html lang="en" dir="ltr" suppressHydrationWarning>
|
||||
<Head faviconGlyph="✦" />
|
||||
<body>
|
||||
<Layout
|
||||
banner={<Banner storageKey="Frogstats">Frogstats Alpha</Banner>}
|
||||
navbar={navbar}
|
||||
footer={<Footer>Copyright {new Date().getFullYear()} © Frogstats.</Footer>}
|
||||
editLink="Edit this page on GitHub"
|
||||
docsRepositoryBase="https://github.com/shuding/nextra/blob/main/examples/docs"
|
||||
sidebar={{ defaultMenuCollapseLevel: 1 }}
|
||||
pageMap={pageMap}
|
||||
>
|
||||
{children}
|
||||
</Layout>
|
||||
</body>
|
||||
</html>
|
||||
)
|
||||
}
|
BIN
docs/src/app/opengraph-image.png
Normal file
After Width: | Height: | Size: 928 KiB |
14
docs/src/app/page.jsx
Normal file
|
@ -0,0 +1,14 @@
|
|||
export default function IndexPage() {
|
||||
return (
|
||||
<h1
|
||||
style={{
|
||||
textAlign: 'center',
|
||||
fontSize: 64,
|
||||
margin: '25vh 0',
|
||||
fontWeight: 'bold'
|
||||
}}
|
||||
>
|
||||
Index page
|
||||
</h1>
|
||||
)
|
||||
}
|
14
docs/src/app/showcase/(overview)/page.jsx
Normal file
|
@ -0,0 +1,14 @@
|
|||
export default function Page() {
|
||||
return (
|
||||
<h1
|
||||
style={{
|
||||
textAlign: 'center',
|
||||
fontSize: 64,
|
||||
margin: '25vh 0',
|
||||
fontWeight: 'bold'
|
||||
}}
|
||||
>
|
||||
Showcase
|
||||
</h1>
|
||||
)
|
||||
}
|
7
docs/src/content/_meta.js
Normal file
|
@ -0,0 +1,7 @@
|
|||
export default {
|
||||
index: "",
|
||||
"self-hosting": "",
|
||||
features: "",
|
||||
themes: "",
|
||||
advanced: "",
|
||||
};
|
56
docs/src/content/advanced/code-highlighting.mdx
Normal file
|
@ -0,0 +1,56 @@
|
|||
# Code Highlighting
|
||||
|
||||
Nextra uses [Shiki](https://shiki.style) and
|
||||
[Rehype Pretty Code](https://github.com/FormidableLabs/prism-react-renderer) to
|
||||
highlight the code blocks. This section covers how you can customize it.
|
||||
|
||||
## Meta strings
|
||||
|
||||
### Highlight lines
|
||||
|
||||
````mdx
|
||||
```jsx {1,3-5}
|
||||
import 'nextra-theme-docs/style.css'
|
||||
|
||||
export default function Nextra({ Component, pageProps }) {
|
||||
const getLayout = Component.getLayout || (page => page)
|
||||
return getLayout(<Component {...pageProps} />)
|
||||
}
|
||||
```
|
||||
````
|
||||
|
||||
```jsx {1,4-5}
|
||||
import 'nextra-theme-docs/style.css'
|
||||
|
||||
export default function Nextra({ Component, pageProps }) {
|
||||
const getLayout = Component.getLayout || (page => page)
|
||||
return getLayout(<Component {...pageProps} />)
|
||||
}
|
||||
```
|
||||
|
||||
### Title
|
||||
|
||||
````mdx
|
||||
```jsx filename="_app.js"
|
||||
import 'nextra-theme-docs/style.css'
|
||||
|
||||
export default function Nextra({ Component, pageProps }) {
|
||||
const getLayout = Component.getLayout || (page => page)
|
||||
return getLayout(<Component {...pageProps} />)
|
||||
}
|
||||
```
|
||||
````
|
||||
|
||||
```jsx filename="_app.js"
|
||||
import 'nextra-theme-docs/style.css'
|
||||
|
||||
export default function Nextra({ Component, pageProps }) {
|
||||
const getLayout = Component.getLayout || (page => page)
|
||||
return getLayout(<Component {...pageProps} />)
|
||||
}
|
||||
```
|
||||
|
||||
## Supported Languages
|
||||
|
||||
You can find a list of supported languages
|
||||
[here](https://github.com/shikijs/shiki/blob/main/docs/languages.md).
|
8
docs/src/content/features/_meta.js
Normal file
|
@ -0,0 +1,8 @@
|
|||
export default {
|
||||
mdx: '',
|
||||
ssg: '',
|
||||
i18n: '',
|
||||
image: '',
|
||||
themes: '',
|
||||
latex: ''
|
||||
}
|
54
docs/src/content/features/i18n.mdx
Normal file
|
@ -0,0 +1,54 @@
|
|||
# Next.js I18n
|
||||
|
||||
> [!NOTE]
|
||||
>
|
||||
> This feature is only available in the docs theme.
|
||||
|
||||
Nextra supports
|
||||
[Next.js Internationalized Routing](https://nextjs.org/docs/advanced-features/i18n-routing)
|
||||
out of the box.
|
||||
|
||||
To add multi-language pages to your Nextra application, just need to config
|
||||
`i18n` in `next.config.mjs`:
|
||||
|
||||
```js filename="next.config.mjs"
|
||||
import nextra from 'nextra'
|
||||
|
||||
const withNextra = nextra({
|
||||
theme: 'nextra-theme-docs',
|
||||
themeConfig: './theme.config.js'
|
||||
})
|
||||
|
||||
export default withNextra({
|
||||
i18n: {
|
||||
locales: ['en', 'zh', 'de'],
|
||||
defaultLocale: 'en'
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
Then, add the locale codes to your file extensions (required for the default
|
||||
locale too):
|
||||
|
||||
```text
|
||||
/pages
|
||||
index.en.md
|
||||
index.zh.md
|
||||
index.de.md
|
||||
meta.en.json
|
||||
meta.zh.json
|
||||
meta.de.json
|
||||
...
|
||||
```
|
||||
|
||||
Finally, add the `i18n` option to your `theme.config.js` to configure the
|
||||
language dropdown:
|
||||
|
||||
```jsx filename="theme.config.js"
|
||||
i18n: [
|
||||
{ locale: 'en', text: 'English' },
|
||||
{ locale: 'zh', text: '中文' },
|
||||
{ locale: 'de', text: 'Deutsch' },
|
||||
{ locale: 'ar', text: 'العربية', direction: 'rtl' }
|
||||
]
|
||||
```
|
34
docs/src/content/features/image.mdx
Normal file
|
@ -0,0 +1,34 @@
|
|||
# Next.js Image
|
||||
|
||||
You can use
|
||||
[Next.js Image](https://nextjs.org/docs/basic-features/image-optimization)
|
||||
directly in MDX.
|
||||
|
||||
If the `demo.png` file is located at `/public/demo.png`, you can use the code
|
||||
below to display it:
|
||||
|
||||
```mdx
|
||||
import Image from 'next/image'
|
||||
|
||||
<Image src="/demo.png" alt="Hello" width={500} height={500} />
|
||||
```
|
||||
|
||||
## Static Image
|
||||
|
||||
> [!NOTE]
|
||||
>
|
||||
> This feature is enabled via `staticImage: true` in the Nextra config by
|
||||
> default.
|
||||
|
||||
Nextra also supports automatic static image imports, you no longer need to
|
||||
specify the width and height of the image manually, and you can directly use the
|
||||
Markdown syntax to display the same image:
|
||||
|
||||
```mdx
|
||||

|
||||
```
|
||||
|
||||
With Next.js Image, there will be no layout shift, and a beautiful blurry
|
||||
placeholder will be shown by default when loading the images:
|
||||
|
||||

|
34
docs/src/content/features/latex.mdx
Normal file
|
@ -0,0 +1,34 @@
|
|||
{/* <link rel="stylesheet"> is unsupported in Metadata API https://nextjs.org/docs/app/api-reference/functions/generate-metadata#unsupported-metadata */}
|
||||
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://cdn.jsdelivr.net/npm/katex/dist/katex.css"
|
||||
/>
|
||||
|
||||
# LaTeX
|
||||
|
||||
Nextra uses [KaTeX](https://katex.org) to render LaTeX expressions directly in
|
||||
MDX. To enable LaTeX support, you must add the following to your
|
||||
`next.config.mjs`:
|
||||
|
||||
```js filename="next.config.mjs"
|
||||
import nextra from 'nextra'
|
||||
|
||||
const withNextra = nextra({
|
||||
latex: true
|
||||
})
|
||||
|
||||
export default withNextra()
|
||||
```
|
||||
|
||||
Using LaTeX within MDX is as simple as wrapping your expression in `$$` or `$`.
|
||||
For example, the following code
|
||||
|
||||
```latex
|
||||
$\sqrt{a^2 + b^2}$
|
||||
```
|
||||
|
||||
will be rendered as: $\sqrt{a^2 + b^2}$
|
||||
|
||||
To learn more about KaTeX and its supported functions, visit their
|
||||
[documentation](https://katex.org/docs/supported.html).
|
159
docs/src/content/features/mdx.mdx
Normal file
|
@ -0,0 +1,159 @@
|
|||
import { compileMdx } from 'nextra/compile'
|
||||
import { Callout } from 'nextra/components'
|
||||
import { MDXRemote } from 'nextra/mdx-remote'
|
||||
|
||||
# MDX
|
||||
|
||||
With Nextra, all your `.md` and `.mdx` files under the pages directory will be
|
||||
rendered with [MDX](https://mdxjs.com/about), it's an advanced Markdown format
|
||||
with React component support.
|
||||
|
||||
You can use import and use React components inside your Markdown files like
|
||||
this:
|
||||
|
||||
export async function Demo() {
|
||||
const mdx = `import { Callout } from 'nextra/components'
|
||||
|
||||
**Markdown With React Components**
|
||||
|
||||
<Callout emoji="✅">
|
||||
**MDX** (the library), at its core, transforms MDX (the syntax) to JSX. It
|
||||
receives an MDX string and outputs a _JSX string_. It does this by parsing the
|
||||
MDX document to a syntax tree and then generates a JSX document from that
|
||||
tree.
|
||||
</Callout>`
|
||||
const rawJs = await compileMdx(`~~~mdx filename="example.mdx"
|
||||
${mdx}
|
||||
~~~
|
||||
|
||||
Generates:
|
||||
|
||||
${mdx}`)
|
||||
return <MDXRemote compiledSource={rawJs} components={{ Callout }} />
|
||||
}
|
||||
|
||||
<Demo />
|
||||
|
||||
## Headings
|
||||
|
||||
# **Hello**, This Is a _Title_ Inside `h1`
|
||||
|
||||
## **Hello**, This Is a _Title_ Inside `h2`
|
||||
|
||||
### **Hello**, This Is a _Title_ Inside `h3`
|
||||
|
||||
#### **Hello**, This Is a _Title_ Inside `h4`
|
||||
|
||||
##### **Hello**, This Is a _Title_ Inside `h5`
|
||||
|
||||
###### **Hello**, This Is a _Title_ Inside `h6`
|
||||
|
||||
## List
|
||||
|
||||
1. one
|
||||
1. two
|
||||
1. three
|
||||
|
||||
- one
|
||||
- two
|
||||
- three
|
||||
|
||||
## Task List
|
||||
|
||||
```mdx
|
||||
- [x] Write the press release
|
||||
- [ ] Update the website
|
||||
- [ ] Contact the media
|
||||
```
|
||||
|
||||
Renders
|
||||
|
||||
- [x] Write the press release
|
||||
- [ ] Update the website
|
||||
- [ ] Contact the media
|
||||
|
||||
## Syntax Highlighting
|
||||
|
||||
Automatic syntax highlighting
|
||||
|
||||
````mdx
|
||||
```js
|
||||
console.log('hello, world')
|
||||
```
|
||||
````
|
||||
|
||||
Renders:
|
||||
|
||||
```js
|
||||
console.log('hello, world')
|
||||
```
|
||||
|
||||
You can also add the `{line|range}` modifier to highlight specific lines:
|
||||
|
||||
````mdx
|
||||
```jsx {4,6-8}
|
||||
import useSWR from 'swr'
|
||||
|
||||
function Profile() {
|
||||
const { data, error } = useSWR('/api/user', fetcher)
|
||||
|
||||
if (error) return <div>failed to load</div>
|
||||
if (!data) return <div>loading...</div>
|
||||
return <div>hello {data.name}!</div>
|
||||
}
|
||||
```
|
||||
````
|
||||
|
||||
```jsx {4,6-8}
|
||||
import useSWR from 'swr'
|
||||
|
||||
function Profile() {
|
||||
const { data, error } = useSWR('/api/user', fetcher)
|
||||
|
||||
if (error) return <div>failed to load</div>
|
||||
if (!data) return <div>loading...</div>
|
||||
return <div>hello {data.name}!</div>
|
||||
}
|
||||
```
|
||||
|
||||
## Inline Code
|
||||
|
||||
You can use \`content\` to wrap inline code content like: `let x = 1`.
|
||||
|
||||
## Blockquote
|
||||
|
||||
> Where some people measure progress in answers-right per test or tests-passed
|
||||
> per year, we are more interested in Sistine-Chapel-Ceilings per Lifetime.
|
||||
>
|
||||
> — Alan Kay, A Personal Computer for Children of All Ages
|
||||
|
||||
Nested quotes:
|
||||
|
||||
> > Where some people measure progress in answers-right per test or tests-passed
|
||||
> > per year, we are more interested in Sistine-Chapel-Ceilings per Lifetime.
|
||||
> >
|
||||
> > — Alan Kay, A Personal Computer for Children of All Ages
|
||||
>
|
||||
> This is **great**.
|
||||
>
|
||||
> — Shu Ding.
|
||||
|
||||
## Table
|
||||
|
||||
| Syntax | Description | Test Text |
|
||||
| :------------ | :---------: | ----------: |
|
||||
| Header | Title | Here's this |
|
||||
| Paragraph | Text | And more |
|
||||
| Strikethrough | | ~~Text~~ |
|
||||
|
||||
## React Components
|
||||
|
||||
React components and Markdown can be **mixed together**, for instance:
|
||||
|
||||
```mdx
|
||||
<Callout>Give [**Nextra**](https://github.com/shuding/nextra) a star!</Callout>
|
||||
```
|
||||
|
||||
Renders:
|
||||
|
||||
<Callout>Give [**Nextra**](https://github.com/shuding/nextra) a star!</Callout>
|
45
docs/src/content/features/ssg.mdx
Normal file
|
@ -0,0 +1,45 @@
|
|||
# Next.js Static Rendering
|
||||
|
||||
[Static Rendering](https://nextjs.org/docs/app/building-your-application/rendering/server-components#static-rendering-default)
|
||||
is default server rendering strategy, where routes are rendered at **build
|
||||
time** or in the background after
|
||||
[data revalidation](https://nextjs.org/docs/app/building-your-application/data-fetching/incremental-static-regeneration).
|
||||
The result is cached and can be distributed via a
|
||||
[Content Delivery Network (CDN)](https://developer.mozilla.org/docs/Glossary/CDN)
|
||||
for optimal performance.
|
||||
|
||||
Static rendering is ideal for routes with non-personalized data that can be
|
||||
determined at build time, such as blog posts or product pages.
|
||||
|
||||
export async function Stars() {
|
||||
let stars = 0
|
||||
try {
|
||||
const response = await fetch('https://api.github.com/repos/shuding/nextra')
|
||||
const repo = await response.json()
|
||||
stars = repo.stargazers_count
|
||||
} catch {
|
||||
/* Ignore if there is an error, due rate limiting on CI */
|
||||
}
|
||||
return <b>{stars}</b>
|
||||
}
|
||||
|
||||
> Nextra has <Stars /> stars on GitHub!
|
||||
|
||||
The number above was generated at build time via MDX server components. With
|
||||
[Incremental Static Regeneration](https://nextjs.org/docs/app/building-your-application/data-fetching/incremental-static-regeneration)
|
||||
enabled, it will be kept up to date.
|
||||
|
||||
---
|
||||
|
||||
Here's the MDX code for the example above:
|
||||
|
||||
```js filename="ssg.mdx"
|
||||
export async function Stars() {
|
||||
const response = await fetch(`https://api.github.com/repos/shuding/nextra`)
|
||||
const repo = await response.json()
|
||||
const stars = repo.stargazers_count || 0
|
||||
return <b>{stars}</b>
|
||||
}
|
||||
|
||||
> Nextra has <Stars /> stars on GitHub!
|
||||
```
|
16
docs/src/content/features/themes.mdx
Normal file
|
@ -0,0 +1,16 @@
|
|||
# Themes
|
||||
|
||||
Nextra itself is basically a plugin that normalizes your Markdown routes in
|
||||
Next.js into structural data, and it doesn't handle any styling related thing. A
|
||||
**theme** is what renders your actual pages, it works like a layout component in
|
||||
React.
|
||||
|
||||
Nextra has 2 official themes that you can use:
|
||||
|
||||
- [Docs Theme](/themes/docs)
|
||||
- [Blog Theme](/themes/blog)
|
||||
|
||||
You can also extend your own themes. Here's a great starter example by
|
||||
[@jaredpalmer](https://github.com/jaredpalmer):
|
||||
|
||||
- [Nextra Blank Custom Theme/Boilerplate Example](https://github.com/jaredpalmer/nextra-blank-custom-theme)
|
17
docs/src/content/index.mdx
Normal file
|
@ -0,0 +1,17 @@
|
|||
import { Bleed } from 'nextra/components'
|
||||
|
||||
# Introduction
|
||||
|
||||
**Frogstats** is an open source web and products analytics platform. Check out our [live demo](https://tracking.tomato.gg) using a real production site that sends over **10,000,000** events a month.
|
||||
|
||||
### Key Features
|
||||
|
||||
- Extremely comprehensive prebuilt analytics dashboards
|
||||
- Cookieless and privacy-friendly
|
||||
- Ability to make your dashboard public
|
||||
- Support for organizations
|
||||
- Advanced product analytics like funnels, user retention, user journeys, and custom reports
|
||||
|
||||
You can either self-host Frogstats, or use our hosted cloud version.
|
||||
|
||||
<Bleed></Bleed>
|
22
docs/src/content/mermaid.mdx
Normal file
|
@ -0,0 +1,22 @@
|
|||
# Mermaid
|
||||
|
||||
```mermaid
|
||||
graph TD;
|
||||
subgraph AA [Consumers]
|
||||
A[Mobile app];
|
||||
B[Web app];
|
||||
C[Node.js client];
|
||||
end
|
||||
subgraph BB [Services]
|
||||
E[REST API];
|
||||
F[GraphQL API];
|
||||
G[SOAP API];
|
||||
end
|
||||
Z[GraphQL API];
|
||||
A --> Z;
|
||||
B --> Z;
|
||||
C --> Z;
|
||||
Z --> E;
|
||||
Z --> F;
|
||||
Z --> G;
|
||||
```
|
3
docs/src/content/page.mdx
Normal file
|
@ -0,0 +1,3 @@
|
|||
# Just Page
|
||||
|
||||
{/* this file should not be treated as App Router page */}
|
105
docs/src/content/self-hosting.mdx
Normal file
|
@ -0,0 +1,105 @@
|
|||
import { Steps } from 'nextra/components'
|
||||
|
||||
# Self Hosting
|
||||
|
||||
You can self-host Frogstats by following the steps below.
|
||||
|
||||
|
||||
## Create manually
|
||||
|
||||
Nextra works like a Next.js plugin, and it accepts a theme config (layout) to
|
||||
render the page. To start: [^3]
|
||||
|
||||
<Steps>
|
||||
### Install Next.js, Nextra and React [^1]
|
||||
|
||||
{/* ```sh npm2yarn
|
||||
npm i react react-dom next nextra
|
||||
``` */}
|
||||
|
||||
### Install the docs theme [^2]
|
||||
|
||||
```sh npm2yarn
|
||||
npm i nextra-theme-docs
|
||||
```
|
||||
|
||||
### Create the following Next.js config and theme config under the root directory
|
||||
|
||||
```js filename="next.config.mjs"
|
||||
import nextra from 'nextra'
|
||||
|
||||
const withNextra = nextra({
|
||||
theme: 'nextra-theme-blog',
|
||||
themeConfig: './theme.config.js'
|
||||
})
|
||||
export default withNextra()
|
||||
```
|
||||
|
||||
### Create a `theme.config.js` file for the docs theme
|
||||
|
||||
```js filename="theme.config.js"
|
||||
export default {
|
||||
project: {
|
||||
link: 'https://github.com/shuding/nextra' // GitHub link in the navbar
|
||||
},
|
||||
docsRepositoryBase: 'https://github.com/shuding/nextra/blob/master', // base URL for the docs repository
|
||||
getNextSeoProps: () => ({ titleTemplate: '%s – Nextra' }),
|
||||
navigation: true,
|
||||
darkMode: true,
|
||||
footer: {
|
||||
text: `MIT ${new Date().getFullYear()} © Shu Ding.`
|
||||
},
|
||||
editLink: {
|
||||
text: 'Edit this page on GitHub'
|
||||
},
|
||||
logo: (
|
||||
<>
|
||||
<svg>...</svg>
|
||||
<span>Next.js Static Site Generator</span>
|
||||
</>
|
||||
),
|
||||
head: (
|
||||
<>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta name="description" content="Nextra: the next docs builder" />
|
||||
<meta name="og:title" content="Nextra: the next docs builder" />
|
||||
</>
|
||||
),
|
||||
primaryHue: {
|
||||
dark: 204,
|
||||
light: 212
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
> [!NOTE]
|
||||
>
|
||||
> More configuration options for the docs theme can be found
|
||||
> [here](/themes/docs/configuration).
|
||||
|
||||
### You are good to go! Run `next dev` to start
|
||||
|
||||
</Steps>
|
||||
|
||||
---
|
||||
|
||||
<span id="sidebar-and-anchor-links" />
|
||||
|
||||
> [!NOTE]
|
||||
>
|
||||
> Any `.md` or `.mdx` file will turn into a doc page and be displayed in
|
||||
> sidebar. You can also create a `_meta.js` file to customize the page order and
|
||||
> title. <br /> Check the source code: https://github.com/shuding/nextra for
|
||||
> more information.
|
||||
|
||||
> [!TIP]
|
||||
>
|
||||
> You can also use
|
||||
> [`<style jsx>`](https://nextjs.org/docs/basic-features/built-in-css-support#css-in-js)
|
||||
> to style elements inside `theme.config.js`.
|
||||
|
||||
[^1]: Install Next.js, Nextra and React.
|
||||
|
||||
[^2]: Install the docs theme.
|
||||
|
||||
[^3]: To start.
|
4
docs/src/content/themes/_meta.js
Normal file
|
@ -0,0 +1,4 @@
|
|||
export default {
|
||||
docs: 'Docs Theme',
|
||||
blog: 'Blog Theme'
|
||||
}
|
3
docs/src/content/themes/blog/_meta.js
Normal file
|
@ -0,0 +1,3 @@
|
|||
export default {
|
||||
index: ''
|
||||
}
|
96
docs/src/content/themes/blog/index.mdx
Normal file
|
@ -0,0 +1,96 @@
|
|||
---
|
||||
sidebarTitle: Installation
|
||||
---
|
||||
|
||||
# Get Started
|
||||
|
||||
import { Steps } from 'nextra/components'
|
||||
|
||||
## Configurations
|
||||
|
||||
Similar to the docs theme, you can install the blog theme with the following
|
||||
commands:
|
||||
|
||||
<Steps>
|
||||
|
||||
### Install Next.js, Nextra and React
|
||||
|
||||
```sh npm2yarn
|
||||
npm i next nextra react react-dom
|
||||
```
|
||||
|
||||
### Install the blog theme
|
||||
|
||||
```sh npm2yarn
|
||||
npm i nextra-theme-blog
|
||||
```
|
||||
|
||||
### Create the following Next.js config and theme config under the root directory:
|
||||
|
||||
```js filename="next.config.mjs"
|
||||
import nextra from 'nextra'
|
||||
|
||||
const withNextra = nextra({
|
||||
theme: 'nextra-theme-blog',
|
||||
themeConfig: './theme.config.js'
|
||||
})
|
||||
export default withNextra()
|
||||
```
|
||||
|
||||
```jsx filename="theme.config.js"
|
||||
export default {
|
||||
footer: <p>MIT 2021 © Nextra.</p>,
|
||||
head: ({ title, meta }) => (
|
||||
<>
|
||||
{meta.description && (
|
||||
<meta name="description" content={meta.description} />
|
||||
)}
|
||||
{meta.tag && <meta name="keywords" content={meta.tag} />}
|
||||
{meta.author && <meta name="author" content={meta.author} />}
|
||||
</>
|
||||
),
|
||||
readMore: 'Read More →',
|
||||
titleSuffix: null,
|
||||
postFooter: null,
|
||||
cusdis: {
|
||||
appId: 'your_app_id',
|
||||
host: 'your_host(optional)',
|
||||
lang: 'your_lang'
|
||||
},
|
||||
darkMode: false,
|
||||
navs: [
|
||||
{
|
||||
url: 'https://github.com/shuding/nextra',
|
||||
name: 'Nextra'
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### Create `pages/_app.js` and include the theme stylesheet:
|
||||
|
||||
```jsx filename="_app.js"
|
||||
import 'nextra-theme-blog/style.css'
|
||||
|
||||
export default function Nextra({ Component, pageProps }) {
|
||||
const getLayout = Component.getLayout || (page => page)
|
||||
return <Component {...pageProps} />
|
||||
}
|
||||
```
|
||||
|
||||
### You are good to go!
|
||||
|
||||
</Steps>
|
||||
|
||||
---
|
||||
|
||||
> [!TIP]
|
||||
>
|
||||
> You can also use
|
||||
> [`<style jsx>`](https://nextjs.org/docs/basic-features/built-in-css-support#css-in-js)
|
||||
> to style elements inside `theme.config.js`.
|
||||
|
||||
> [!NOTE]
|
||||
>
|
||||
> An example of the blog theme can be found
|
||||
> [here](https://github.com/vercel-solutions/nextjs-portfolio-starter).
|
6
docs/src/content/themes/docs/_meta.js
Normal file
|
@ -0,0 +1,6 @@
|
|||
export default {
|
||||
index: '',
|
||||
configuration: '',
|
||||
callout: '',
|
||||
bleed: ''
|
||||
}
|
82
docs/src/content/themes/docs/bleed.mdx
Normal file
|
@ -0,0 +1,82 @@
|
|||
---
|
||||
sidebarTitle: Bleed
|
||||
---
|
||||
|
||||
# Bleed Component
|
||||
|
||||
A built-in component provided by `nextra-theme-docs`.
|
||||
|
||||
## Example
|
||||
|
||||
When wrapping your content with `<Bleed>`, it will be slightly wider than the
|
||||
container and will overflow on both sides.
|
||||
|
||||
import { Bleed } from 'nextra/components'
|
||||
|
||||
<Bleed>
|
||||
<div style={{ border: '1px solid #888', padding: '4rem 2.5rem', textAlign: 'center' }}>
|
||||
_There is nothing to writing. All you do is sit down at a typewriter and **bleed**._
|
||||
|
||||
— Ernest Hemingway
|
||||
|
||||
</div>
|
||||
</Bleed>
|
||||
|
||||
It provides a better reading experience when you want to present some graphical
|
||||
information, which normally looks nicer in a larger size.
|
||||
|
||||
For example, you can put text, image, video or any component inside:
|
||||
|
||||
<Bleed>
|
||||
<iframe
|
||||
width="100%"
|
||||
height="430"
|
||||
src="https://youtube.com/embed/3hccXiXI0u8"
|
||||
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
|
||||
allowFullScreen
|
||||
/>
|
||||
</Bleed>
|
||||
|
||||
You can even make it full-bleed using `<Bleed full>`:
|
||||
|
||||
<Bleed full></Bleed>
|
||||
|
||||
## Usage
|
||||
|
||||
### MDX component
|
||||
|
||||
```mdx filename="bleed.mdx"
|
||||
<Bleed>Hey, I can use **Markdown** syntax here.</Bleed>
|
||||
|
||||
<Bleed full></Bleed>
|
||||
|
||||
<Bleed full>
|
||||
<iframe
|
||||
src="https://codesandbox.io/embed/swr-states-4une7"
|
||||
width="100%"
|
||||
height="500px"
|
||||
title="SWR-States"
|
||||
/>
|
||||
</Bleed>
|
||||
```
|
||||
|
||||
### React Component
|
||||
|
||||
```jsx filename="bleed.jsx"
|
||||
import { Bleed } from 'nextra/components'
|
||||
|
||||
<Bleed>Hey, I can use **Markdown** syntax here.</Bleed>
|
||||
|
||||
<Bleed full>
|
||||

|
||||
</Bleed>
|
||||
|
||||
<Bleed full>
|
||||
<iframe
|
||||
src="https://codesandbox.io/embed/swr-states-4une7"
|
||||
width="100%"
|
||||
height="500px"
|
||||
title="SWR-States"
|
||||
/>
|
||||
</Bleed>
|
||||
```
|
66
docs/src/content/themes/docs/callout.mdx
Normal file
|
@ -0,0 +1,66 @@
|
|||
---
|
||||
sidebarTitle: Callout
|
||||
---
|
||||
|
||||
# Callout Component
|
||||
|
||||
A built-in component provided by `nextra/components`.
|
||||
|
||||
## Example
|
||||
|
||||
import { Callout } from 'nextra/components'
|
||||
|
||||
<Callout>
|
||||
A **callout** is a short piece of text intended to attract attention.
|
||||
</Callout>
|
||||
|
||||
## Usage
|
||||
|
||||
### Default
|
||||
|
||||
<Callout emoji="👾">
|
||||
**Space Invaders** is a 1978 shoot 'em up arcade game developed by Tomohiro
|
||||
Nishikado.
|
||||
</Callout>
|
||||
|
||||
```mdx
|
||||
<Callout emoji="👾">
|
||||
**Space Invaders** is a 1978 shoot 'em up arcade game developed by Tomohiro
|
||||
Nishikado.
|
||||
</Callout>
|
||||
```
|
||||
|
||||
### Warning
|
||||
|
||||
<Callout type="warning">This API will be deprecated soon.</Callout>
|
||||
|
||||
```mdx
|
||||
<Callout type="warning">This API will be deprecated soon.</Callout>
|
||||
```
|
||||
|
||||
### Error
|
||||
|
||||
<Callout type="error">
|
||||
This is a dangerous feature that can cause everything to explode.
|
||||
</Callout>
|
||||
|
||||
```mdx
|
||||
<Callout type="error">
|
||||
This is a dangerous feature that can cause everything to explode.
|
||||
</Callout>
|
||||
```
|
||||
|
||||
### React Component
|
||||
|
||||
```jsx filename="callout.jsx"
|
||||
import { Callout } from 'nextra/components'
|
||||
|
||||
const Component = () => {
|
||||
return (
|
||||
<Callout emoji="👾">
|
||||
**Space Invaders** is a 1978 shoot 'em up arcade game developed by
|
||||
Tomohiro Nishikado.
|
||||
</Callout>
|
||||
)
|
||||
}
|
||||
```
|
510
docs/src/content/themes/docs/configuration.mdx
Normal file
|
@ -0,0 +1,510 @@
|
|||
# Configuration
|
||||
|
||||
To configure the theme, edit or create the `theme.config.js` file in the root
|
||||
directory. The file looks something like this:
|
||||
|
||||
```js filename="theme.config.js"
|
||||
export default {
|
||||
projectLink: 'https://gitlab.com/librewolf-community/browser',
|
||||
titleSuffix: ' – Nextra',
|
||||
footerText: `MIT ${new Date().getFullYear()} © Nextra.`
|
||||
}
|
||||
```
|
||||
|
||||
## `projectLink`
|
||||
|
||||
The URL that the button in the top right will point to.
|
||||
|
||||
**Type:** `string`
|
||||
|
||||
**Default:** `https://github.com/shuding/nextra`
|
||||
|
||||
**Example:**
|
||||
|
||||
```js filename="theme.config.js"
|
||||
export default {
|
||||
projectLink: 'https://gitlab.com/librewolf-community/browser'
|
||||
}
|
||||
```
|
||||
|
||||
## `projectLinkIcon`
|
||||
|
||||
Changes the icon that is shown in the top right.
|
||||
|
||||
**Type:** `ReactNode | React.FC<{ locale: string }>{:ts}`
|
||||
|
||||
**Default:** GitHub icon
|
||||
|
||||
**Example:**
|
||||
|
||||
```jsx filename="theme.config.jsx"
|
||||
import Gitlab from '@geist-ui/react-icons/gitlab'
|
||||
|
||||
export default {
|
||||
projectLinkIcon: ({ locale }) => <Gitlab />
|
||||
}
|
||||
```
|
||||
|
||||
## `docsRepositoryBase`
|
||||
|
||||
The base URL of the GitHub repository the docs are located in. This will be used
|
||||
for the `Edit this Page on GitHub` button.
|
||||
|
||||
**Type:** `string`
|
||||
|
||||
**Default:** `https://github.com/shuding/nextra`
|
||||
|
||||
**Example:**
|
||||
|
||||
```js filename="theme.config.js"
|
||||
export default {
|
||||
docsRepositoryBase: 'https://github.com/shuding/nextra'
|
||||
}
|
||||
```
|
||||
|
||||
## `titleSuffix`
|
||||
|
||||
Suffix that will be added to page titles in the URL bar.
|
||||
|
||||
**Type:** `string`
|
||||
|
||||
**Default:** `– Nextra`
|
||||
|
||||
**Example:**
|
||||
|
||||
```js filename="theme.config.js"
|
||||
export default {
|
||||
titleSuffix: '– Nextra'
|
||||
}
|
||||
```
|
||||
|
||||
## `nextLinks` and `prevLinks`
|
||||
|
||||
Specifies if arrows are being shown at the bottom of a page showing the next and
|
||||
previous page, like the ones at the bottom of this page.
|
||||
|
||||
**Type:** `boolean`
|
||||
|
||||
**Default:** `true`
|
||||
|
||||
**Example:**
|
||||
|
||||
```js filename="theme.config.js"
|
||||
export default {
|
||||
nextLinks: true,
|
||||
prevLinks: true
|
||||
}
|
||||
```
|
||||
|
||||
## `search`
|
||||
|
||||
Specifies if a search box should be shown in the top right.
|
||||
|
||||
**Type:** `boolean`
|
||||
|
||||
**Default:** `true`
|
||||
|
||||
**Example:**
|
||||
|
||||
```js filename="theme.config.js"
|
||||
export default {
|
||||
search: true
|
||||
}
|
||||
```
|
||||
|
||||
## `searchPlaceholder`
|
||||
|
||||
Specifies if a search box should be shown in the top right.
|
||||
|
||||
**Type:** `string | ((props: { locale: string }) => string){:ts}`
|
||||
|
||||
**Example:**
|
||||
|
||||
```js filename="theme.config.js"
|
||||
export default {
|
||||
searchPlaceholder({ locale }) {
|
||||
if (locale === 'zh-CN') return '搜索文档...'
|
||||
return 'Search documentation...'
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## `customSearch`
|
||||
|
||||
A custom component to display instead of the search bar in the top right, for
|
||||
example Algolia.
|
||||
|
||||
**Type:** `ReactNode`
|
||||
|
||||
**Example:**
|
||||
|
||||
```jsx filename="theme.config.jsx"
|
||||
import Search from 'your-search'
|
||||
|
||||
export default {
|
||||
customSearch: <Search />
|
||||
}
|
||||
```
|
||||
|
||||
## `darkMode`
|
||||
|
||||
Specifies if the user can select a dark mode.
|
||||
|
||||
**Type:** `boolean`
|
||||
|
||||
**Default:** `true`
|
||||
|
||||
**Example:**
|
||||
|
||||
```js filename="theme.config.js"
|
||||
export default {
|
||||
darkMode: true
|
||||
}
|
||||
```
|
||||
|
||||
## `defaultMenuCollapseLevel`
|
||||
|
||||
Specifies the folder level at which the menu on the left is collapsed by
|
||||
default.
|
||||
|
||||
**Type:** `number`
|
||||
|
||||
**Default:** `2`
|
||||
|
||||
**Example:**
|
||||
|
||||
```js filename="theme.config.js"
|
||||
export default {
|
||||
defaultMenuCollapseLevel: 2
|
||||
}
|
||||
```
|
||||
|
||||
## `footer`
|
||||
|
||||
Specifies if the footer should be shown.
|
||||
|
||||
**Type:** `boolean`
|
||||
|
||||
**Default:** `true`
|
||||
|
||||
**Example:**
|
||||
|
||||
```js filename="theme.config.js"
|
||||
export default {
|
||||
footer: true
|
||||
}
|
||||
```
|
||||
|
||||
## `footerText`
|
||||
|
||||
The text that is shown on the left of the footer.
|
||||
|
||||
**Type:** `ReactNode | React.FC<PropsWithChildren<{ locale: string }>>{:ts}`
|
||||
|
||||
**Example:**
|
||||
|
||||
```js filename="theme.config.js"
|
||||
export default {
|
||||
footerText: ({ locale }) => `MIT ${new Date().getFullYear()} © Nextra.`
|
||||
}
|
||||
```
|
||||
|
||||
## `footerEditLink`
|
||||
|
||||
The components that should be shown on the link that leads to the editable page
|
||||
on the repository.
|
||||
|
||||
**Type:** `ReactNode | React.FC<PropsWithChildren<{ locale: string }>>{:ts}`
|
||||
|
||||
**Default:** `Edit this page`
|
||||
|
||||
**Example:**
|
||||
|
||||
```js filename="theme.config.js"
|
||||
export default {
|
||||
footerEditLink: ({ locale }) => 'Edit this page on GitHub'
|
||||
}
|
||||
```
|
||||
|
||||
## `feedbackLink`
|
||||
|
||||
The components that should be shown on the link that leads to the issues or
|
||||
discussions of the repository.
|
||||
|
||||
**Type:** `ReactNode | React.FC<PropsWithChildren<{ locale: string }>>{:ts}`
|
||||
|
||||
**Default:** ``
|
||||
|
||||
**Example:**
|
||||
|
||||
```js filename="theme.config.js"
|
||||
export default {
|
||||
feedbackLink: ({ locale }) => 'Question? Give us feedback →'
|
||||
}
|
||||
```
|
||||
|
||||
## `feedbackLabels`
|
||||
|
||||
Label used for create issue or discussion.
|
||||
|
||||
**Type:** `string`
|
||||
|
||||
**Default:** ``
|
||||
|
||||
**Example:**
|
||||
|
||||
```js filename="theme.config.js"
|
||||
export default {
|
||||
feedbackLabels: 'feedbacks'
|
||||
}
|
||||
```
|
||||
|
||||
## `logo`
|
||||
|
||||
The logo in the top left.
|
||||
|
||||
**Type:** `ReactNode | React.FC<PropsWithChildren<{ locale: string }>>{:ts}`
|
||||
|
||||
**Example:**
|
||||
|
||||
```jsx filename="theme.config.jsx"
|
||||
export default {
|
||||
logo: ({ locale }) => (
|
||||
<>
|
||||
<span className="mr-2 hidden font-extrabold md:inline">Nextra</span>
|
||||
<span className="hidden font-normal text-gray-600 md:inline">
|
||||
The Next Docs Builder
|
||||
</span>
|
||||
</>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
## `logoLink`
|
||||
|
||||
Enable automaticaly linking the logo to root, or provide a custom url.
|
||||
|
||||
**Type:** `string` | `boolean`
|
||||
|
||||
**Default:** `true` (links to `/` by default)
|
||||
|
||||
**Example:**
|
||||
|
||||
```js filename="theme.config.js"
|
||||
export default {
|
||||
logoLink: '/about'
|
||||
}
|
||||
```
|
||||
|
||||
Or to disable the logo link:
|
||||
|
||||
```js filename="theme.config.js"
|
||||
export default {
|
||||
logoLink: false
|
||||
}
|
||||
```
|
||||
|
||||
## `head`
|
||||
|
||||
The head that should be inserted into the html document.
|
||||
|
||||
**Type:**
|
||||
`ReactNode | React.FC<PropsWithChildren<{ locale: string; config: DocsThemeConfig; title: string; meta: Record<string, any> }>>{:ts}`
|
||||
|
||||
**Example:**
|
||||
|
||||
```jsx filename="theme.config.jsx"
|
||||
export default {
|
||||
head: (
|
||||
<>
|
||||
<meta name="msapplication-TileColor" content="#fff" />
|
||||
<meta httpEquiv="Content-Language" content="en" />
|
||||
<meta name="description" content="Nextra: the next docs builder" />
|
||||
<meta name="twitter:card" content="summary_large_image" />
|
||||
<meta name="twitter:site" content="@shuding_" />
|
||||
<meta property="og:title" content="Nextra: the next docs builder" />
|
||||
<meta property="og:description" content="Nextra: the next docs builder" />
|
||||
<meta name="apple-mobile-web-app-title" content="Nextra" />
|
||||
</>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
## `direction`
|
||||
|
||||
The direction of the text on the page
|
||||
|
||||
**Type:** `'ltr' | 'rtl'`
|
||||
|
||||
**Default:** `'ltr'`
|
||||
|
||||
**Example:**
|
||||
|
||||
```js filename="theme.config.js"
|
||||
export default {
|
||||
direction: 'ltr'
|
||||
}
|
||||
```
|
||||
|
||||
## `floatTOC`
|
||||
|
||||
Specifies if the table of contents of a page (the headings) should be displayed
|
||||
floating on the right instead of being integrated in the menu on the left.
|
||||
|
||||
**Type:** `boolean`
|
||||
|
||||
**Default:** `false`
|
||||
|
||||
**Example:**
|
||||
|
||||
```js filename="theme.config.js"
|
||||
export default {
|
||||
floatTOC: false
|
||||
}
|
||||
```
|
||||
|
||||
## `projectChatLink`
|
||||
|
||||
The URL that the chat button in the top right will point to.
|
||||
|
||||
**Type:** `string`
|
||||
|
||||
**Example:**
|
||||
|
||||
```js filename="theme.config.js"
|
||||
export default {
|
||||
projectChatLink: 'https://discord.gg/hEM84NMkRv'
|
||||
}
|
||||
```
|
||||
|
||||
## `projectChatLinkIcon`
|
||||
|
||||
The icon component that is used as the chat button
|
||||
|
||||
**Type:** `ReactNode`
|
||||
|
||||
**Example:**
|
||||
|
||||
```jsx filename="theme.config.jsx"
|
||||
export default {
|
||||
projectChatLinkIcon: <Discord />
|
||||
}
|
||||
```
|
||||
|
||||
## `banner`
|
||||
|
||||
The banner content that will display at top of the page.
|
||||
|
||||
**Type:** `ReactNode | React.FC<PropsWithChildren<{ locale: string }>>{:ts}`
|
||||
|
||||
**Example:**
|
||||
|
||||
```js filename="theme.config.js"
|
||||
export default {
|
||||
banner: ({ locale }) => 'Nextra 2'
|
||||
}
|
||||
```
|
||||
|
||||
## `bannerKey`
|
||||
|
||||
The key that is used to control the display of banner in localStorage.
|
||||
|
||||
**Type:** `string`
|
||||
|
||||
**Default:** `'nextra-banner'`
|
||||
|
||||
**Example:**
|
||||
|
||||
```js filename="theme.config.js"
|
||||
export default {
|
||||
bannerKey: 'Nextra-banner'
|
||||
}
|
||||
```
|
||||
|
||||
## `gitTimestamp`
|
||||
|
||||
The component that is used to display timestamp of the last commit of current
|
||||
page.
|
||||
|
||||
**Type:**
|
||||
`string | React.FC<PropsWithChildren<{ locale: string; timestamp: Date }>>{:ts}`
|
||||
|
||||
**Example:**
|
||||
|
||||
```js filename="theme.config.js"
|
||||
export default {
|
||||
gitTimestamp: 'Last updated on'
|
||||
}
|
||||
```
|
||||
|
||||
## `tocExtraContent`
|
||||
|
||||
The extra content that is displayed under the table of contents.
|
||||
|
||||
**Type:** `ReactNode | React.FC<PropsWithChildren<unknown>>{:ts}`
|
||||
|
||||
**Example:**
|
||||
|
||||
```jsx filename="theme.config.jsx"
|
||||
export default {
|
||||
tocExtraContent() {
|
||||
return <img src="https://placecats.com/300/200" alt="" />
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## `i18n`
|
||||
|
||||
The internationalization (i18n) config. See more [here](/features/i18n).
|
||||
|
||||
## `faviconGlyph`
|
||||
|
||||
A glyph that should be used as a favicon.
|
||||
|
||||
**Type:** `char`
|
||||
|
||||
**Example:**
|
||||
|
||||
```js filename="theme.config.js"
|
||||
export default {
|
||||
faviconGlyph: '🐱'
|
||||
}
|
||||
```
|
||||
|
||||
## `search`
|
||||
|
||||
Enable Nextra built-in search
|
||||
|
||||
**Type:** `boolean | { codeblocks: boolean }`
|
||||
|
||||
**Example:**
|
||||
|
||||
```js filename="next.config.mjs"
|
||||
import nextra from 'nextra'
|
||||
|
||||
const withNextra = nextra({
|
||||
theme: 'nextra-theme-blog',
|
||||
themeConfig: './theme.config.js',
|
||||
search: {
|
||||
codeblocks: false
|
||||
}
|
||||
})
|
||||
export default withNextra()
|
||||
```
|
||||
|
||||
## `searchResultEmpty`
|
||||
|
||||
Empty component for search result.
|
||||
|
||||
**Type:** `boolean | { codeblocks: boolean }`
|
||||
|
||||
**Example:**
|
||||
|
||||
```js filename="theme.config.js"
|
||||
export default {
|
||||
searchResultEmpty({ locale }) {
|
||||
if (locale === 'zh-CN') return '未查找到结果'
|
||||
return 'No results found'
|
||||
}
|
||||
}
|
||||
```
|
82
docs/src/content/themes/docs/index.mdx
Normal file
|
@ -0,0 +1,82 @@
|
|||
---
|
||||
sidebarTitle: Installation
|
||||
---
|
||||
|
||||
# Docs Theme
|
||||
|
||||
import { Steps } from 'nextra/components'
|
||||
|
||||
> [!NOTE]
|
||||
>
|
||||
> This website is built with the docs theme.
|
||||
|
||||
you can install the blog theme with the following commands:
|
||||
|
||||
## Getting start
|
||||
|
||||
<Steps>
|
||||
|
||||
### Install Next.js, Nextra and React
|
||||
|
||||
```sh npm2yarn
|
||||
npm i react react-dom next nextra
|
||||
```
|
||||
|
||||
### Install the docs theme
|
||||
|
||||
```sh npm2yarn
|
||||
npm i nextra-theme-docs
|
||||
```
|
||||
|
||||
### Create the following Next.js config and theme config under the root directory:
|
||||
|
||||
```jsx filename="next.config.mjs"
|
||||
import nextra from 'nextra'
|
||||
|
||||
const withNextra = nextra({
|
||||
theme: 'nextra-theme-blog',
|
||||
themeConfig: './theme.config.js'
|
||||
})
|
||||
export default withNextra()
|
||||
```
|
||||
|
||||
```jsx filename="theme.config.js"
|
||||
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,
|
||||
customSearch: null, // customizable, you can use algolia for example
|
||||
darkMode: true,
|
||||
footer: true,
|
||||
footerText: `MIT ${new Date().getFullYear()} © Shu Ding.`,
|
||||
footerEditLink: `Edit this page on GitHub`,
|
||||
logo: (
|
||||
<>
|
||||
<svg>...</svg>
|
||||
<span>Next.js Static Site Generator</span>
|
||||
</>
|
||||
),
|
||||
head: (
|
||||
<>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta name="description" content="Nextra: the next docs builder" />
|
||||
<meta name="og:title" content="Nextra: the next docs builder" />
|
||||
</>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### You are good to go!
|
||||
|
||||
</Steps>
|
||||
|
||||
---
|
||||
|
||||
> [!TIP]
|
||||
>
|
||||
> You can also use
|
||||
> [`<style jsx>`](https://nextjs.org/docs/basic-features/built-in-css-support#css-in-js)
|
||||
> to style elements inside `theme.config.js`.
|
81
docs/src/content/themes/docs/tabs.mdx
Normal file
|
@ -0,0 +1,81 @@
|
|||
---
|
||||
sidebarTitle: Tabs
|
||||
---
|
||||
|
||||
# Tabs Component
|
||||
|
||||
A built-in component provided by `nextra-theme-docs`.
|
||||
|
||||
## Example
|
||||
|
||||
import { Tabs } from 'nextra/components'
|
||||
|
||||
<Tabs items={['JavaScript', 'C++', {label:'C', disabled: true}, 'Python']} defaultIndex={1}>
|
||||
<Tabs.Tab>
|
||||
```js filename="hi.js"
|
||||
import { useState, useEffect } from 'react';
|
||||
```
|
||||
</Tabs.Tab>
|
||||
<Tabs.Tab>
|
||||
```cpp filename="hi.cpp"
|
||||
#include <iostream>
|
||||
```
|
||||
</Tabs.Tab>
|
||||
<Tabs.Tab>
|
||||
```c filename="hi.c"
|
||||
#include <stdio.h>
|
||||
```
|
||||
</Tabs.Tab>
|
||||
<Tabs.Tab>
|
||||
```python filename="hello.py"
|
||||
print('Hello, world!')
|
||||
```
|
||||
</Tabs.Tab>
|
||||
</Tabs>
|
||||
|
||||
## Usage
|
||||
|
||||
### MDX component
|
||||
|
||||
````mdx filename="tabs.mdx"
|
||||
<Tabs items={['JavaScript', 'C++', {label:'C', disabled: true}, 'Python']} defaultIndex={1}>
|
||||
<Tabs.Tab>
|
||||
```js filename="hi.js"
|
||||
import { useState, useEffect } from 'react';
|
||||
```
|
||||
</Tabs.Tab>
|
||||
<Tabs.Tab>
|
||||
```cpp filename="hi.cpp"
|
||||
#include <iostream>
|
||||
```
|
||||
</Tabs.Tab>
|
||||
<Tabs.Tab>
|
||||
```c filename="hi.c"
|
||||
#include <stdio.h>
|
||||
```
|
||||
</Tabs.Tab>
|
||||
<Tabs.Tab>
|
||||
```python filename="hello.py"
|
||||
print('Hello, world!')
|
||||
```
|
||||
</Tabs.Tab>
|
||||
</Tabs>
|
||||
````
|
||||
|
||||
### React Component
|
||||
|
||||
```jsx filename="tabs.jsx"
|
||||
import { Tabs } from 'nextra/components'
|
||||
|
||||
const items = ['1', '2', '3', '4']
|
||||
const defaultIndex = 1
|
||||
const Component = () => (
|
||||
<Tabs items={items} defaultIndex={defaultIndex}>
|
||||
<Tabs.Tab>1</Tab>
|
||||
<Tabs.Tab>2</Tab>
|
||||
<Tabs.Tab>3</Tab>
|
||||
<Tabs.Tab>4</Tab>
|
||||
</Tabs>
|
||||
)
|
||||
export default Component
|
||||
```
|