create-unmint 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +57 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +499 -0
- package/package.json +48 -0
- package/template/LICENSE +21 -0
- package/template/README.md +278 -0
- package/template/__tests__/components/callout.test.tsx +46 -0
- package/template/__tests__/components/card.test.tsx +59 -0
- package/template/__tests__/components/tabs.test.tsx +61 -0
- package/template/__tests__/theme-config.test.ts +49 -0
- package/template/__tests__/utils.test.ts +25 -0
- package/template/app/api/og/route.tsx +90 -0
- package/template/app/api/search/route.ts +6 -0
- package/template/app/components/docs/docs-pager.tsx +41 -0
- package/template/app/components/docs/docs-sidebar.tsx +143 -0
- package/template/app/components/docs/docs-toc.tsx +61 -0
- package/template/app/components/docs/mdx/accordion.tsx +54 -0
- package/template/app/components/docs/mdx/callout.tsx +102 -0
- package/template/app/components/docs/mdx/card.tsx +110 -0
- package/template/app/components/docs/mdx/code-block.tsx +42 -0
- package/template/app/components/docs/mdx/frame.tsx +14 -0
- package/template/app/components/docs/mdx/index.tsx +167 -0
- package/template/app/components/docs/mdx/pre.tsx +82 -0
- package/template/app/components/docs/mdx/steps.tsx +59 -0
- package/template/app/components/docs/mdx/tabs.tsx +60 -0
- package/template/app/components/docs/mdx/youtube.tsx +18 -0
- package/template/app/components/docs/search-dialog.tsx +281 -0
- package/template/app/components/docs/theme-toggle.tsx +35 -0
- package/template/app/docs/[[...slug]]/page.tsx +139 -0
- package/template/app/docs/layout.tsx +98 -0
- package/template/app/globals.css +151 -0
- package/template/app/layout.tsx +33 -0
- package/template/app/page.tsx +5 -0
- package/template/app/providers/theme-provider.tsx +8 -0
- package/template/content/docs/components.mdx +82 -0
- package/template/content/docs/customization.mdx +34 -0
- package/template/content/docs/deployment.mdx +28 -0
- package/template/content/docs/index.mdx +91 -0
- package/template/content/docs/meta.json +13 -0
- package/template/content/docs/quickstart.mdx +110 -0
- package/template/content/docs/theming.mdx +41 -0
- package/template/lib/docs-source.ts +7 -0
- package/template/lib/theme-config.ts +89 -0
- package/template/lib/utils.ts +6 -0
- package/template/next.config.mjs +10 -0
- package/template/package-lock.json +10695 -0
- package/template/package.json +45 -0
- package/template/postcss.config.mjs +7 -0
- package/template/public/logo.png +0 -0
- package/template/public/logo.svg +9 -0
- package/template/public/logo.txt +1 -0
- package/template/source.config.ts +22 -0
- package/template/tailwind.config.ts +34 -0
- package/template/tsconfig.json +33 -0
- package/template/vitest.config.ts +16 -0
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
|
|
3
|
+
import { useTheme } from 'next-themes'
|
|
4
|
+
import { useEffect, useState } from 'react'
|
|
5
|
+
|
|
6
|
+
export function ThemeToggle() {
|
|
7
|
+
const { theme, setTheme } = useTheme()
|
|
8
|
+
const [mounted, setMounted] = useState(false)
|
|
9
|
+
|
|
10
|
+
useEffect(() => {
|
|
11
|
+
setMounted(true)
|
|
12
|
+
}, [])
|
|
13
|
+
|
|
14
|
+
if (!mounted) {
|
|
15
|
+
return <div className="w-9 h-9" />
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
return (
|
|
19
|
+
<button
|
|
20
|
+
onClick={() => setTheme(theme === 'dark' ? 'light' : 'dark')}
|
|
21
|
+
className="flex items-center justify-center w-9 h-9 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-800 transition-colors"
|
|
22
|
+
aria-label="Toggle theme"
|
|
23
|
+
>
|
|
24
|
+
{theme === 'dark' ? (
|
|
25
|
+
<svg className="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2}>
|
|
26
|
+
<path strokeLinecap="round" strokeLinejoin="round" d="M20.354 15.354A9 9 0 018.646 3.646 9.003 9.003 0 0012 21a9.003 9.003 0 008.354-5.646z" />
|
|
27
|
+
</svg>
|
|
28
|
+
) : (
|
|
29
|
+
<svg className="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2}>
|
|
30
|
+
<path strokeLinecap="round" strokeLinejoin="round" d="M12 3v1m0 16v1m9-9h-1M4 12H3m15.364 6.364l-.707-.707M6.343 6.343l-.707-.707m12.728 0l-.707.707M6.343 17.657l-.707.707M16 12a4 4 0 11-8 0 4 4 0 018 0z" />
|
|
31
|
+
</svg>
|
|
32
|
+
)}
|
|
33
|
+
</button>
|
|
34
|
+
)
|
|
35
|
+
}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import { source } from '@/lib/docs-source'
|
|
2
|
+
import { notFound } from 'next/navigation'
|
|
3
|
+
import { DocsTOC } from '../../components/docs/docs-toc'
|
|
4
|
+
import { DocsPager } from '../../components/docs/docs-pager'
|
|
5
|
+
import { getMDXComponents } from '../../components/docs/mdx'
|
|
6
|
+
import { findNeighbour } from 'fumadocs-core/page-tree'
|
|
7
|
+
import type { Metadata } from 'next'
|
|
8
|
+
import type { Root, Node } from 'fumadocs-core/page-tree'
|
|
9
|
+
import { siteConfig, themeConfig } from '@/lib/theme-config'
|
|
10
|
+
|
|
11
|
+
interface PageProps {
|
|
12
|
+
params: Promise<{ slug?: string[] }>
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
// Find the section separator that precedes this page in the tree
|
|
16
|
+
function findSectionName(tree: Root, pageUrl: string): string {
|
|
17
|
+
let lastSeparator = 'Documentation'
|
|
18
|
+
|
|
19
|
+
function traverse(nodes: Node[]): string | null {
|
|
20
|
+
for (const node of nodes) {
|
|
21
|
+
if (node.type === 'separator') {
|
|
22
|
+
// node.name can be ReactNode, convert to string safely
|
|
23
|
+
lastSeparator = typeof node.name === 'string' ? node.name : 'Documentation'
|
|
24
|
+
} else if (node.type === 'page' && node.url === pageUrl) {
|
|
25
|
+
return lastSeparator
|
|
26
|
+
} else if (node.type === 'folder' && node.children) {
|
|
27
|
+
const result = traverse(node.children)
|
|
28
|
+
if (result) return result
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
return null
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return traverse(tree.children) || lastSeparator
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export default async function DocsPage({ params }: PageProps) {
|
|
38
|
+
const { slug } = await params
|
|
39
|
+
const page = source.getPage(slug)
|
|
40
|
+
|
|
41
|
+
if (!page) notFound()
|
|
42
|
+
|
|
43
|
+
const MDXContent = page.data.body
|
|
44
|
+
const toc = page.data.toc
|
|
45
|
+
|
|
46
|
+
// Get prev/next navigation using fumadocs utility
|
|
47
|
+
const tree = source.pageTree
|
|
48
|
+
const neighbours = findNeighbour(tree, page.url)
|
|
49
|
+
|
|
50
|
+
// Find section name for the header banner
|
|
51
|
+
const sectionName = findSectionName(tree, page.url)
|
|
52
|
+
|
|
53
|
+
return (
|
|
54
|
+
<div className="flex gap-8">
|
|
55
|
+
{/* Main content */}
|
|
56
|
+
<article className="flex-1 min-w-0 max-w-3xl">
|
|
57
|
+
{/* Header banner */}
|
|
58
|
+
<header className="mb-8 pb-6 border-b border-border">
|
|
59
|
+
<p className="text-sm text-[var(--accent)] font-medium mb-2">
|
|
60
|
+
{sectionName}
|
|
61
|
+
</p>
|
|
62
|
+
<h1 className="text-3xl font-bold text-foreground">
|
|
63
|
+
{page.data.title}
|
|
64
|
+
</h1>
|
|
65
|
+
{page.data.description && (
|
|
66
|
+
<p className="mt-3 text-base text-muted-foreground">
|
|
67
|
+
{page.data.description}
|
|
68
|
+
</p>
|
|
69
|
+
)}
|
|
70
|
+
</header>
|
|
71
|
+
|
|
72
|
+
{/* MDX content */}
|
|
73
|
+
<div className="prose prose-slate dark:prose-invert max-w-none">
|
|
74
|
+
<MDXContent components={getMDXComponents()} />
|
|
75
|
+
</div>
|
|
76
|
+
|
|
77
|
+
<DocsPager
|
|
78
|
+
previous={neighbours.previous ? {
|
|
79
|
+
name: typeof neighbours.previous.name === 'string' ? neighbours.previous.name : 'Previous',
|
|
80
|
+
url: neighbours.previous.url
|
|
81
|
+
} : undefined}
|
|
82
|
+
next={neighbours.next ? {
|
|
83
|
+
name: typeof neighbours.next.name === 'string' ? neighbours.next.name : 'Next',
|
|
84
|
+
url: neighbours.next.url
|
|
85
|
+
} : undefined}
|
|
86
|
+
/>
|
|
87
|
+
</article>
|
|
88
|
+
|
|
89
|
+
{/* Table of contents */}
|
|
90
|
+
<DocsTOC toc={toc} />
|
|
91
|
+
</div>
|
|
92
|
+
)
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export async function generateStaticParams() {
|
|
96
|
+
return source.generateParams()
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export async function generateMetadata({ params }: PageProps): Promise<Metadata> {
|
|
100
|
+
const { slug } = await params
|
|
101
|
+
const page = source.getPage(slug)
|
|
102
|
+
|
|
103
|
+
if (!page) return {}
|
|
104
|
+
|
|
105
|
+
const tree = source.pageTree
|
|
106
|
+
const section = findSectionName(tree, page.url)
|
|
107
|
+
const title = page.data.title
|
|
108
|
+
const description = page.data.description
|
|
109
|
+
|
|
110
|
+
// Build OG image URL with query params
|
|
111
|
+
const ogImageUrl = new URL(`${siteConfig.url}/api/og`)
|
|
112
|
+
ogImageUrl.searchParams.set('title', title)
|
|
113
|
+
ogImageUrl.searchParams.set('section', section)
|
|
114
|
+
|
|
115
|
+
return {
|
|
116
|
+
title,
|
|
117
|
+
description,
|
|
118
|
+
openGraph: {
|
|
119
|
+
title,
|
|
120
|
+
description,
|
|
121
|
+
type: 'article',
|
|
122
|
+
url: `${siteConfig.url}${page.url}`,
|
|
123
|
+
images: [
|
|
124
|
+
{
|
|
125
|
+
url: ogImageUrl.toString(),
|
|
126
|
+
width: 1200,
|
|
127
|
+
height: 630,
|
|
128
|
+
alt: title,
|
|
129
|
+
},
|
|
130
|
+
],
|
|
131
|
+
},
|
|
132
|
+
twitter: {
|
|
133
|
+
card: 'summary_large_image',
|
|
134
|
+
title,
|
|
135
|
+
description,
|
|
136
|
+
images: [ogImageUrl.toString()],
|
|
137
|
+
},
|
|
138
|
+
}
|
|
139
|
+
}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import Link from 'next/link'
|
|
2
|
+
import Image from 'next/image'
|
|
3
|
+
import { source } from '@/lib/docs-source'
|
|
4
|
+
import { DocsSidebar } from '../components/docs/docs-sidebar'
|
|
5
|
+
import { SearchTrigger } from '../components/docs/search-dialog'
|
|
6
|
+
import { ThemeToggle } from '../components/docs/theme-toggle'
|
|
7
|
+
import { siteConfig } from '@/lib/theme-config'
|
|
8
|
+
|
|
9
|
+
export default function DocsLayout({
|
|
10
|
+
children,
|
|
11
|
+
}: {
|
|
12
|
+
children: React.ReactNode
|
|
13
|
+
}) {
|
|
14
|
+
const tree = source.pageTree
|
|
15
|
+
|
|
16
|
+
return (
|
|
17
|
+
<div className="min-h-screen flex flex-col">
|
|
18
|
+
{/* Header */}
|
|
19
|
+
<header className="sticky top-0 z-50 w-full border-b border-border bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60">
|
|
20
|
+
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
|
21
|
+
<div className="flex h-16 items-center justify-between">
|
|
22
|
+
{/* Logo */}
|
|
23
|
+
<Link href="/" className="flex items-center gap-2">
|
|
24
|
+
{siteConfig.logo.src && (
|
|
25
|
+
<Image
|
|
26
|
+
src={siteConfig.logo.src}
|
|
27
|
+
alt={siteConfig.logo.alt}
|
|
28
|
+
width={siteConfig.logo.width}
|
|
29
|
+
height={siteConfig.logo.height}
|
|
30
|
+
className="dark:invert"
|
|
31
|
+
/>
|
|
32
|
+
)}
|
|
33
|
+
<span className="font-semibold text-lg">{siteConfig.name}</span>
|
|
34
|
+
</Link>
|
|
35
|
+
|
|
36
|
+
{/* Center: Search */}
|
|
37
|
+
<div className="flex-1 flex justify-center px-4">
|
|
38
|
+
<SearchTrigger />
|
|
39
|
+
</div>
|
|
40
|
+
|
|
41
|
+
{/* Right: Links */}
|
|
42
|
+
<div className="flex items-center gap-2">
|
|
43
|
+
{siteConfig.links.github && (
|
|
44
|
+
<a
|
|
45
|
+
href={siteConfig.links.github}
|
|
46
|
+
target="_blank"
|
|
47
|
+
rel="noopener noreferrer"
|
|
48
|
+
className="p-2 text-muted-foreground hover:text-foreground transition-colors"
|
|
49
|
+
>
|
|
50
|
+
<svg className="w-5 h-5" fill="currentColor" viewBox="0 0 24 24">
|
|
51
|
+
<path fillRule="evenodd" d="M12 2C6.477 2 2 6.484 2 12.017c0 4.425 2.865 8.18 6.839 9.504.5.092.682-.217.682-.483 0-.237-.008-.868-.013-1.703-2.782.605-3.369-1.343-3.369-1.343-.454-1.158-1.11-1.466-1.11-1.466-.908-.62.069-.608.069-.608 1.003.07 1.531 1.032 1.531 1.032.892 1.53 2.341 1.088 2.91.832.092-.647.35-1.088.636-1.338-2.22-.253-4.555-1.113-4.555-4.951 0-1.093.39-1.988 1.029-2.688-.103-.253-.446-1.272.098-2.65 0 0 .84-.27 2.75 1.026A9.564 9.564 0 0112 6.844c.85.004 1.705.115 2.504.337 1.909-1.296 2.747-1.027 2.747-1.027.546 1.379.202 2.398.1 2.651.64.7 1.028 1.595 1.028 2.688 0 3.848-2.339 4.695-4.566 4.943.359.309.678.92.678 1.855 0 1.338-.012 2.419-.012 2.747 0 .268.18.58.688.482A10.019 10.019 0 0022 12.017C22 6.484 17.522 2 12 2z" clipRule="evenodd" />
|
|
52
|
+
</svg>
|
|
53
|
+
</a>
|
|
54
|
+
)}
|
|
55
|
+
<ThemeToggle />
|
|
56
|
+
</div>
|
|
57
|
+
</div>
|
|
58
|
+
</div>
|
|
59
|
+
</header>
|
|
60
|
+
|
|
61
|
+
{/* Main content */}
|
|
62
|
+
<div className="flex-1">
|
|
63
|
+
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
|
|
64
|
+
<div className="flex gap-8">
|
|
65
|
+
<DocsSidebar tree={tree} />
|
|
66
|
+
<main className="flex-1 min-w-0">
|
|
67
|
+
{children}
|
|
68
|
+
</main>
|
|
69
|
+
</div>
|
|
70
|
+
</div>
|
|
71
|
+
</div>
|
|
72
|
+
|
|
73
|
+
{/* Footer */}
|
|
74
|
+
<footer className="border-t border-border py-8">
|
|
75
|
+
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
|
76
|
+
<div className="flex flex-col sm:flex-row justify-between items-center gap-4">
|
|
77
|
+
<p className="text-sm text-muted-foreground">
|
|
78
|
+
{siteConfig.footer.copyright}
|
|
79
|
+
</p>
|
|
80
|
+
<div className="flex gap-4">
|
|
81
|
+
{siteConfig.footer.links.map((link) => (
|
|
82
|
+
<a
|
|
83
|
+
key={link.href}
|
|
84
|
+
href={link.href}
|
|
85
|
+
target="_blank"
|
|
86
|
+
rel="noopener noreferrer"
|
|
87
|
+
className="text-sm text-muted-foreground hover:text-foreground transition-colors"
|
|
88
|
+
>
|
|
89
|
+
{link.label}
|
|
90
|
+
</a>
|
|
91
|
+
))}
|
|
92
|
+
</div>
|
|
93
|
+
</div>
|
|
94
|
+
</div>
|
|
95
|
+
</footer>
|
|
96
|
+
</div>
|
|
97
|
+
)
|
|
98
|
+
}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
@import 'tailwindcss';
|
|
2
|
+
|
|
3
|
+
@custom-variant dark (&:is(.dark *));
|
|
4
|
+
|
|
5
|
+
@theme inline {
|
|
6
|
+
--color-background: var(--background);
|
|
7
|
+
--color-foreground: var(--foreground);
|
|
8
|
+
--color-card: var(--card);
|
|
9
|
+
--color-card-foreground: var(--card-foreground);
|
|
10
|
+
--color-popover: var(--popover);
|
|
11
|
+
--color-popover-foreground: var(--popover-foreground);
|
|
12
|
+
--color-primary: var(--primary);
|
|
13
|
+
--color-primary-foreground: var(--primary-foreground);
|
|
14
|
+
--color-secondary: var(--secondary);
|
|
15
|
+
--color-secondary-foreground: var(--secondary-foreground);
|
|
16
|
+
--color-muted: var(--muted);
|
|
17
|
+
--color-muted-foreground: var(--muted-foreground);
|
|
18
|
+
--color-accent: var(--accent);
|
|
19
|
+
--color-accent-foreground: var(--accent-foreground);
|
|
20
|
+
--color-destructive: var(--destructive);
|
|
21
|
+
--color-border: var(--border);
|
|
22
|
+
--color-input: var(--input);
|
|
23
|
+
--color-ring: var(--ring);
|
|
24
|
+
--font-sans: 'Inter', system-ui, sans-serif;
|
|
25
|
+
--font-mono: 'Fira Code', ui-monospace, monospace;
|
|
26
|
+
--radius-sm: calc(var(--radius) - 4px);
|
|
27
|
+
--radius-md: calc(var(--radius) - 2px);
|
|
28
|
+
--radius-lg: var(--radius);
|
|
29
|
+
--radius-xl: calc(var(--radius) + 4px);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
:root {
|
|
33
|
+
--radius: 0.625rem;
|
|
34
|
+
--background: oklch(1 0 0);
|
|
35
|
+
--foreground: oklch(0.145 0 0);
|
|
36
|
+
--card: oklch(1 0 0);
|
|
37
|
+
--card-foreground: oklch(0.145 0 0);
|
|
38
|
+
--popover: oklch(1 0 0);
|
|
39
|
+
--popover-foreground: oklch(0.145 0 0);
|
|
40
|
+
--primary: oklch(0.205 0 0);
|
|
41
|
+
--primary-foreground: oklch(0.985 0 0);
|
|
42
|
+
--secondary: oklch(0.97 0 0);
|
|
43
|
+
--secondary-foreground: oklch(0.205 0 0);
|
|
44
|
+
--muted: oklch(0.97 0 0);
|
|
45
|
+
--muted-foreground: oklch(0.556 0 0);
|
|
46
|
+
--destructive: oklch(0.577 0.245 27.325);
|
|
47
|
+
--border: oklch(0.922 0 0);
|
|
48
|
+
--input: oklch(0.922 0 0);
|
|
49
|
+
--ring: oklch(0.708 0 0);
|
|
50
|
+
|
|
51
|
+
/* Brand accent colors - customize these for your brand */
|
|
52
|
+
--accent: #0891b2;
|
|
53
|
+
--accent-foreground: #ffffff;
|
|
54
|
+
--accent-muted: rgba(8, 145, 178, 0.1);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
.dark {
|
|
58
|
+
--background: oklch(0.145 0 0);
|
|
59
|
+
--foreground: oklch(0.985 0 0);
|
|
60
|
+
--card: oklch(0.205 0 0);
|
|
61
|
+
--card-foreground: oklch(0.985 0 0);
|
|
62
|
+
--popover: oklch(0.205 0 0);
|
|
63
|
+
--popover-foreground: oklch(0.985 0 0);
|
|
64
|
+
--primary: oklch(0.922 0 0);
|
|
65
|
+
--primary-foreground: oklch(0.205 0 0);
|
|
66
|
+
--secondary: oklch(0.269 0 0);
|
|
67
|
+
--secondary-foreground: oklch(0.985 0 0);
|
|
68
|
+
--muted: oklch(0.269 0 0);
|
|
69
|
+
--muted-foreground: oklch(0.708 0 0);
|
|
70
|
+
--destructive: oklch(0.704 0.191 22.216);
|
|
71
|
+
--border: oklch(1 0 0 / 10%);
|
|
72
|
+
--input: oklch(1 0 0 / 15%);
|
|
73
|
+
--ring: oklch(0.556 0 0);
|
|
74
|
+
|
|
75
|
+
/* Brand accent colors - brighter for dark mode */
|
|
76
|
+
--accent: #22d3ee;
|
|
77
|
+
--accent-foreground: #0f172a;
|
|
78
|
+
--accent-muted: rgba(34, 211, 238, 0.1);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
@layer base {
|
|
82
|
+
* {
|
|
83
|
+
@apply border-border outline-ring/50;
|
|
84
|
+
}
|
|
85
|
+
body {
|
|
86
|
+
@apply bg-background text-foreground;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/* Syntax highlighting - Shiki integration */
|
|
91
|
+
pre {
|
|
92
|
+
overflow-x: auto;
|
|
93
|
+
padding: 1rem;
|
|
94
|
+
border-radius: 0.5rem;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
pre code {
|
|
98
|
+
display: block;
|
|
99
|
+
min-width: max-content;
|
|
100
|
+
background: transparent !important;
|
|
101
|
+
border: none !important;
|
|
102
|
+
padding: 1rem !important;
|
|
103
|
+
margin: 0 !important;
|
|
104
|
+
border-radius: 0 !important;
|
|
105
|
+
color: inherit !important;
|
|
106
|
+
font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
code {
|
|
110
|
+
font-family: var(--font-mono);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/* Shiki dual-theme support */
|
|
114
|
+
pre code span {
|
|
115
|
+
color: var(--shiki-light);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
.dark pre code span {
|
|
119
|
+
color: var(--shiki-dark);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/* Code block line highlighting */
|
|
123
|
+
pre code [data-highlighted-line] {
|
|
124
|
+
background-color: rgba(0, 0, 0, 0.05);
|
|
125
|
+
display: block;
|
|
126
|
+
margin: 0 -1rem;
|
|
127
|
+
padding: 0 1rem;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
.dark pre code [data-highlighted-line] {
|
|
131
|
+
background-color: rgba(255, 255, 255, 0.05);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/* Scrollbar styling */
|
|
135
|
+
::-webkit-scrollbar {
|
|
136
|
+
width: 8px;
|
|
137
|
+
height: 8px;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
::-webkit-scrollbar-track {
|
|
141
|
+
background: transparent;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
::-webkit-scrollbar-thumb {
|
|
145
|
+
background: oklch(0.556 0 0 / 0.3);
|
|
146
|
+
border-radius: 4px;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
::-webkit-scrollbar-thumb:hover {
|
|
150
|
+
background: oklch(0.556 0 0 / 0.5);
|
|
151
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { Metadata } from 'next'
|
|
2
|
+
import { ThemeProvider } from './providers/theme-provider'
|
|
3
|
+
import { siteConfig } from '@/lib/theme-config'
|
|
4
|
+
import './globals.css'
|
|
5
|
+
|
|
6
|
+
export const metadata: Metadata = {
|
|
7
|
+
title: {
|
|
8
|
+
default: siteConfig.name,
|
|
9
|
+
template: `%s | ${siteConfig.name}`,
|
|
10
|
+
},
|
|
11
|
+
description: siteConfig.description,
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export default function RootLayout({
|
|
15
|
+
children,
|
|
16
|
+
}: {
|
|
17
|
+
children: React.ReactNode
|
|
18
|
+
}) {
|
|
19
|
+
return (
|
|
20
|
+
<html lang="en" suppressHydrationWarning>
|
|
21
|
+
<body>
|
|
22
|
+
<ThemeProvider
|
|
23
|
+
attribute="class"
|
|
24
|
+
defaultTheme="system"
|
|
25
|
+
enableSystem
|
|
26
|
+
disableTransitionOnChange
|
|
27
|
+
>
|
|
28
|
+
{children}
|
|
29
|
+
</ThemeProvider>
|
|
30
|
+
</body>
|
|
31
|
+
</html>
|
|
32
|
+
)
|
|
33
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
|
|
3
|
+
import { ThemeProvider as NextThemesProvider } from 'next-themes'
|
|
4
|
+
import type { ThemeProviderProps } from 'next-themes'
|
|
5
|
+
|
|
6
|
+
export function ThemeProvider({ children, ...props }: ThemeProviderProps) {
|
|
7
|
+
return <NextThemesProvider {...props}>{children}</NextThemesProvider>
|
|
8
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Components
|
|
3
|
+
description: Pre-built MDX components for beautiful documentation
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
Unmint includes a rich set of MDX components that you can use in your documentation pages.
|
|
7
|
+
|
|
8
|
+
## Cards
|
|
9
|
+
|
|
10
|
+
Use cards to highlight links or features:
|
|
11
|
+
|
|
12
|
+
<CardGroup cols={2}>
|
|
13
|
+
<Card title="Quick Start" icon="rocket" href="/docs/quickstart">
|
|
14
|
+
Get started in under 5 minutes
|
|
15
|
+
</Card>
|
|
16
|
+
<Card title="Components" icon="code" href="/docs/components">
|
|
17
|
+
Explore available components
|
|
18
|
+
</Card>
|
|
19
|
+
</CardGroup>
|
|
20
|
+
|
|
21
|
+
### Available Icons
|
|
22
|
+
|
|
23
|
+
Cards support these built-in icons: `rocket`, `code`, `book`, `gear`, `plug`, `terminal`.
|
|
24
|
+
|
|
25
|
+
## Callouts
|
|
26
|
+
|
|
27
|
+
Callouts draw attention to important information:
|
|
28
|
+
|
|
29
|
+
<Info>
|
|
30
|
+
This is an info callout for general information.
|
|
31
|
+
</Info>
|
|
32
|
+
|
|
33
|
+
<Tip>
|
|
34
|
+
This is a tip callout for helpful suggestions.
|
|
35
|
+
</Tip>
|
|
36
|
+
|
|
37
|
+
<Warning>
|
|
38
|
+
This is a warning callout for potential issues.
|
|
39
|
+
</Warning>
|
|
40
|
+
|
|
41
|
+
## Steps
|
|
42
|
+
|
|
43
|
+
Use steps for sequential instructions:
|
|
44
|
+
|
|
45
|
+
<Steps>
|
|
46
|
+
<Step title="First Step">
|
|
47
|
+
Do this first.
|
|
48
|
+
</Step>
|
|
49
|
+
<Step title="Second Step">
|
|
50
|
+
Then do this.
|
|
51
|
+
</Step>
|
|
52
|
+
</Steps>
|
|
53
|
+
|
|
54
|
+
## Tabs
|
|
55
|
+
|
|
56
|
+
Organize related content into tabs:
|
|
57
|
+
|
|
58
|
+
<Tabs>
|
|
59
|
+
<Tab title="npm">
|
|
60
|
+
```bash
|
|
61
|
+
npm install my-package
|
|
62
|
+
```
|
|
63
|
+
</Tab>
|
|
64
|
+
<Tab title="yarn">
|
|
65
|
+
```bash
|
|
66
|
+
yarn add my-package
|
|
67
|
+
```
|
|
68
|
+
</Tab>
|
|
69
|
+
</Tabs>
|
|
70
|
+
|
|
71
|
+
## Accordions
|
|
72
|
+
|
|
73
|
+
Collapse content that isn't always needed:
|
|
74
|
+
|
|
75
|
+
<AccordionGroup>
|
|
76
|
+
<Accordion title="What is Unmint?">
|
|
77
|
+
Unmint is a free, open-source documentation system.
|
|
78
|
+
</Accordion>
|
|
79
|
+
<Accordion title="Is it really free?">
|
|
80
|
+
Yes! MIT licensed and free to use.
|
|
81
|
+
</Accordion>
|
|
82
|
+
</AccordionGroup>
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Customization
|
|
3
|
+
description: Advanced customization options
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
## Navigation Structure
|
|
7
|
+
|
|
8
|
+
Edit `content/docs/meta.json`:
|
|
9
|
+
|
|
10
|
+
```json
|
|
11
|
+
{
|
|
12
|
+
"pages": [
|
|
13
|
+
"index",
|
|
14
|
+
"quickstart",
|
|
15
|
+
"---Getting Started---",
|
|
16
|
+
"installation"
|
|
17
|
+
]
|
|
18
|
+
}
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
- **Page references**: Filename without `.mdx`
|
|
22
|
+
- **Separators**: `"---Section Name---"` for headers
|
|
23
|
+
|
|
24
|
+
## Adding Components
|
|
25
|
+
|
|
26
|
+
Create custom MDX components in `app/components/docs/mdx/`:
|
|
27
|
+
|
|
28
|
+
```tsx
|
|
29
|
+
export function MyComponent({ children }) {
|
|
30
|
+
return <div className="my-component">{children}</div>
|
|
31
|
+
}
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Then register in `app/components/docs/mdx/index.tsx`.
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Deployment
|
|
3
|
+
description: Deploy your docs to Vercel, Netlify, or any static host
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
Unmint can be deployed anywhere that supports Next.js.
|
|
7
|
+
|
|
8
|
+
## Vercel (Recommended)
|
|
9
|
+
|
|
10
|
+
<Steps>
|
|
11
|
+
<Step title="Push to GitHub">
|
|
12
|
+
Push your repository to GitHub.
|
|
13
|
+
</Step>
|
|
14
|
+
<Step title="Import to Vercel">
|
|
15
|
+
Go to vercel.com/new and import your repository.
|
|
16
|
+
</Step>
|
|
17
|
+
<Step title="Deploy">
|
|
18
|
+
Vercel will automatically detect Next.js and deploy.
|
|
19
|
+
</Step>
|
|
20
|
+
</Steps>
|
|
21
|
+
|
|
22
|
+
## Build Commands
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
npm run dev # Development
|
|
26
|
+
npm run build # Production build
|
|
27
|
+
npm run start # Start production server
|
|
28
|
+
```
|