chore: add helix-api and workspace config to monorepo
This commit is contained in:
40 files changed
+7145
No files matched your search
@@ -0,0 +1,9 @@
|
||||
# Secrets
|
||||
.env*
|
||||
|
||||
# Dependencies
|
||||
node_modules
|
||||
|
||||
# OS files
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
@@ -0,0 +1,22 @@
|
||||
info:
|
||||
name: Login
|
||||
type: http
|
||||
seq: 1
|
||||
|
||||
http:
|
||||
method: POST
|
||||
url: "{{BaseURL}}/auth/login"
|
||||
body:
|
||||
type: json
|
||||
data: |-
|
||||
{
|
||||
"username": "helix",
|
||||
"password": "123456"
|
||||
}
|
||||
auth: inherit
|
||||
|
||||
settings:
|
||||
encodeUrl: true
|
||||
timeout: 0
|
||||
followRedirects: true
|
||||
maxRedirects: 5
|
||||
@@ -0,0 +1,7 @@
|
||||
info:
|
||||
name: Authentication
|
||||
type: folder
|
||||
seq: 1
|
||||
|
||||
request:
|
||||
auth: inherit
|
||||
@@ -0,0 +1,24 @@
|
||||
info:
|
||||
name: Add Department
|
||||
type: http
|
||||
seq: 1
|
||||
|
||||
http:
|
||||
method: POST
|
||||
url: "{{BaseURL}}/departments"
|
||||
body:
|
||||
type: json
|
||||
data: |-
|
||||
{
|
||||
"name": "Domestic Marketing",
|
||||
"parentId": 10,
|
||||
"sort": null,
|
||||
"status": null
|
||||
}
|
||||
auth: inherit
|
||||
|
||||
settings:
|
||||
encodeUrl: true
|
||||
timeout: 0
|
||||
followRedirects: true
|
||||
maxRedirects: 5
|
||||
@@ -0,0 +1,7 @@
|
||||
info:
|
||||
name: Departments
|
||||
type: folder
|
||||
seq: 2
|
||||
|
||||
request:
|
||||
auth: inherit
|
||||
@@ -0,0 +1,6 @@
|
||||
name: Development
|
||||
variables:
|
||||
- name: BaseURL
|
||||
value: http://localhost:5000
|
||||
- name: language
|
||||
value: zh-CN
|
||||
@@ -0,0 +1,26 @@
|
||||
opencollection: 1.0.0
|
||||
|
||||
info:
|
||||
name: Helix
|
||||
config:
|
||||
proxy:
|
||||
inherit: true
|
||||
config:
|
||||
protocol: http
|
||||
hostname: ""
|
||||
port: ""
|
||||
auth:
|
||||
username: ""
|
||||
password: ""
|
||||
bypassProxy: ""
|
||||
|
||||
request:
|
||||
headers:
|
||||
- name: Accept-Language
|
||||
value: "{{language}}"
|
||||
bundled: false
|
||||
extensions:
|
||||
bruno:
|
||||
ignore:
|
||||
- node_modules
|
||||
- .git
|
||||
@@ -0,0 +1,7 @@
|
||||
.DS_Store
|
||||
/node_modules/
|
||||
|
||||
# React Router
|
||||
/.react-router/
|
||||
/build/
|
||||
.source
|
||||
@@ -0,0 +1,23 @@
|
||||
# Helix API Docs
|
||||
|
||||
Vite + React Router + Fumadocs documentation app with OpenAPI support.
|
||||
|
||||
## Run
|
||||
|
||||
```bash
|
||||
pnpm install
|
||||
pnpm dev
|
||||
```
|
||||
|
||||
Open these pages:
|
||||
|
||||
- `/api-reference`: OpenAPI interactive reference
|
||||
- `/docs`: MDX docs pages
|
||||
|
||||
## Edit OpenAPI
|
||||
|
||||
Manually maintain:
|
||||
|
||||
- `openapi/openapi.yaml`
|
||||
|
||||
After changes, refresh the `/api-reference` page.
|
||||
@@ -0,0 +1,4 @@
|
||||
@import 'tailwindcss';
|
||||
@import 'fumadocs-ui/css/neutral.css';
|
||||
@import 'fumadocs-ui/css/preset.css';
|
||||
@import 'fumadocs-openapi/css/preset.css';
|
||||
@@ -0,0 +1,4 @@
|
||||
import { openapi } from '@/lib/openapi';
|
||||
import { createAPIPage } from 'fumadocs-openapi/ui';
|
||||
|
||||
export const APIPage = createAPIPage(openapi);
|
||||
@@ -0,0 +1,15 @@
|
||||
import defaultMdxComponents from 'fumadocs-ui/mdx';
|
||||
import type { MDXComponents } from 'mdx/types';
|
||||
|
||||
export function getMDXComponents(components?: MDXComponents) {
|
||||
return {
|
||||
...defaultMdxComponents,
|
||||
...components,
|
||||
} satisfies MDXComponents;
|
||||
}
|
||||
|
||||
export const useMDXComponents = getMDXComponents;
|
||||
|
||||
declare global {
|
||||
type MDXProvidedComponents = ReturnType<typeof getMDXComponents>;
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
'use client';
|
||||
import {
|
||||
SearchDialog,
|
||||
SearchDialogClose,
|
||||
SearchDialogContent,
|
||||
SearchDialogHeader,
|
||||
SearchDialogIcon,
|
||||
SearchDialogInput,
|
||||
SearchDialogList,
|
||||
SearchDialogOverlay,
|
||||
type SharedProps,
|
||||
} from 'fumadocs-ui/components/dialog/search';
|
||||
import { useDocsSearch } from 'fumadocs-core/search/client';
|
||||
import { create } from '@orama/orama';
|
||||
import { useI18n } from 'fumadocs-ui/contexts/i18n';
|
||||
|
||||
function initOrama() {
|
||||
return create({
|
||||
schema: { _: 'string' },
|
||||
language: 'english',
|
||||
});
|
||||
}
|
||||
|
||||
export default function DefaultSearchDialog(props: SharedProps) {
|
||||
const { locale } = useI18n();
|
||||
const { search, setSearch, query } = useDocsSearch({
|
||||
type: 'static',
|
||||
initOrama,
|
||||
locale,
|
||||
});
|
||||
|
||||
return (
|
||||
<SearchDialog search={search} onSearchChange={setSearch} isLoading={query.isLoading} {...props}>
|
||||
<SearchDialogOverlay />
|
||||
<SearchDialogContent>
|
||||
<SearchDialogHeader>
|
||||
<SearchDialogIcon />
|
||||
<SearchDialogInput />
|
||||
<SearchDialogClose />
|
||||
</SearchDialogHeader>
|
||||
<SearchDialogList items={query.data !== 'empty' ? query.data : null} />
|
||||
</SearchDialogContent>
|
||||
</SearchDialog>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
export { twMerge as cn } from 'tailwind-merge';
|
||||
@@ -0,0 +1,17 @@
|
||||
import type { BaseLayoutProps } from 'fumadocs-ui/layouts/shared';
|
||||
|
||||
// fill this with your actual GitHub info, for example:
|
||||
export const gitConfig = {
|
||||
user: 'fuma-nama',
|
||||
repo: 'fumadocs',
|
||||
branch: 'main',
|
||||
};
|
||||
|
||||
export function baseOptions(): BaseLayoutProps {
|
||||
return {
|
||||
nav: {
|
||||
title: 'React Router',
|
||||
},
|
||||
githubUrl: `https://github.com/${gitConfig.user}/${gitConfig.repo}`,
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
import path from 'node:path';
|
||||
import { createOpenAPI } from 'fumadocs-openapi/server';
|
||||
|
||||
export const openapi = createOpenAPI({
|
||||
input: () => ({
|
||||
helix: path.resolve('./openapi/openapi.yaml'),
|
||||
}),
|
||||
});
|
||||
@@ -0,0 +1,15 @@
|
||||
import { loader, type InferPageType } from 'fumadocs-core/source';
|
||||
import { docs } from 'collections/server';
|
||||
|
||||
export const source = loader({
|
||||
source: docs.toFumadocsSource(),
|
||||
baseUrl: '/docs',
|
||||
});
|
||||
|
||||
export async function getLLMText(page: InferPageType<typeof source>) {
|
||||
const processed = await page.data.getText('processed');
|
||||
|
||||
return `# ${page.data.title} (${page.url})
|
||||
|
||||
${processed}`;
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
import { getLLMText, source } from '@/lib/source';
|
||||
|
||||
export async function loader() {
|
||||
const scan = source.getPages().map(getLLMText);
|
||||
const scanned = await Promise.all(scan);
|
||||
|
||||
return new Response(scanned.join('\n\n'));
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
import { source } from '@/lib/source';
|
||||
import { llms } from 'fumadocs-core/source';
|
||||
|
||||
export function loader() {
|
||||
return new Response(llms(source).index());
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
import type { Route } from './+types/mdx';
|
||||
import { getLLMText, source } from '@/lib/source';
|
||||
|
||||
export async function loader({ params }: Route.LoaderArgs) {
|
||||
const slugs = params['*'].split('/').filter((v) => v.length > 0);
|
||||
// remove the appended "index.mdx" that's added to avoid React Router issues
|
||||
slugs.pop();
|
||||
const page = source.getPage(slugs);
|
||||
if (!page) {
|
||||
return new Response('not found', { status: 404 });
|
||||
}
|
||||
return new Response(await getLLMText(page), {
|
||||
headers: {
|
||||
'Content-Type': 'text/markdown',
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
import {
|
||||
isRouteErrorResponse,
|
||||
Links,
|
||||
Meta,
|
||||
Outlet,
|
||||
Scripts,
|
||||
ScrollRestoration,
|
||||
} from 'react-router';
|
||||
import { RootProvider } from 'fumadocs-ui/provider/react-router';
|
||||
import type { Route } from './+types/root';
|
||||
import './app.css';
|
||||
import SearchDialog from '@/components/search';
|
||||
import NotFound from './routes/not-found';
|
||||
|
||||
export const links: Route.LinksFunction = () => [
|
||||
{ rel: 'preconnect', href: 'https://fonts.googleapis.com' },
|
||||
{
|
||||
rel: 'preconnect',
|
||||
href: 'https://fonts.gstatic.com',
|
||||
crossOrigin: 'anonymous',
|
||||
},
|
||||
{
|
||||
rel: 'stylesheet',
|
||||
href: 'https://fonts.googleapis.com/css2?family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&display=swap',
|
||||
},
|
||||
];
|
||||
|
||||
export function Layout({ children }: { children: React.ReactNode }) {
|
||||
return (
|
||||
<html lang="en" suppressHydrationWarning>
|
||||
<head>
|
||||
<meta charSet="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<Meta />
|
||||
<Links />
|
||||
</head>
|
||||
<body className="flex flex-col min-h-screen">
|
||||
<RootProvider search={{ SearchDialog }}>{children}</RootProvider>
|
||||
<ScrollRestoration />
|
||||
<Scripts />
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
}
|
||||
|
||||
export default function App() {
|
||||
return <Outlet />;
|
||||
}
|
||||
|
||||
export function ErrorBoundary({ error }: Route.ErrorBoundaryProps) {
|
||||
let message = 'Oops!';
|
||||
let details = 'An unexpected error occurred.';
|
||||
let stack: string | undefined;
|
||||
|
||||
if (isRouteErrorResponse(error)) {
|
||||
if (error.status === 404) return <NotFound />;
|
||||
message = 'Error';
|
||||
details = error.statusText;
|
||||
} else if (import.meta.env.DEV && error && error instanceof Error) {
|
||||
details = error.message;
|
||||
stack = error.stack;
|
||||
}
|
||||
|
||||
return (
|
||||
<main className="pt-16 p-4 w-full max-w-[1400px] mx-auto">
|
||||
<h1>{message}</h1>
|
||||
<p>{details}</p>
|
||||
{stack && (
|
||||
<pre className="w-full p-4 overflow-x-auto">
|
||||
<code>{stack}</code>
|
||||
</pre>
|
||||
)}
|
||||
</main>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
import { index, route, type RouteConfig } from '@react-router/dev/routes';
|
||||
|
||||
export default [
|
||||
index('routes/home.tsx'),
|
||||
route('docs/*', 'routes/docs.tsx'),
|
||||
route('api-reference', 'routes/api-reference.tsx'),
|
||||
route('api/search', 'routes/search.ts'),
|
||||
|
||||
// LLM integration:
|
||||
route('llms.txt', 'llms/index.ts'),
|
||||
route('llms-full.txt', 'llms/full.ts'),
|
||||
route('llms.mdx/docs/*', 'llms/mdx.ts'),
|
||||
|
||||
route('*', 'routes/not-found.tsx'),
|
||||
] satisfies RouteConfig;
|
||||
@@ -0,0 +1,29 @@
|
||||
import type { Route } from './+types/api-reference';
|
||||
import { DocsLayout } from 'fumadocs-ui/layouts/docs';
|
||||
import { DocsBody, DocsDescription, DocsPage, DocsTitle } from 'fumadocs-ui/layouts/docs/page';
|
||||
import { source } from '@/lib/source';
|
||||
import { baseOptions } from '@/lib/layout.shared';
|
||||
import { APIPage } from '@/components/api-page';
|
||||
|
||||
export function meta({}: Route.MetaArgs) {
|
||||
return [
|
||||
{ title: 'API Reference' },
|
||||
{ name: 'description', content: 'OpenAPI reference for Helix API.' },
|
||||
];
|
||||
}
|
||||
|
||||
export default function ApiReference() {
|
||||
return (
|
||||
<DocsLayout {...baseOptions()} tree={source.getPageTree()}>
|
||||
<DocsPage full>
|
||||
<DocsTitle>API Reference</DocsTitle>
|
||||
<DocsDescription>
|
||||
Edit openapi/openapi.yaml to maintain this API documentation.
|
||||
</DocsDescription>
|
||||
<DocsBody>
|
||||
<APIPage document="helix" />
|
||||
</DocsBody>
|
||||
</DocsPage>
|
||||
</DocsLayout>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
import type { Route } from './+types/docs';
|
||||
import { DocsLayout } from 'fumadocs-ui/layouts/docs';
|
||||
import {
|
||||
DocsBody,
|
||||
DocsDescription,
|
||||
DocsPage,
|
||||
DocsTitle,
|
||||
MarkdownCopyButton,
|
||||
ViewOptionsPopover,
|
||||
} from 'fumadocs-ui/layouts/docs/page';
|
||||
import { source } from '@/lib/source';
|
||||
import browserCollections from 'collections/browser';
|
||||
import { baseOptions, gitConfig } from '@/lib/layout.shared';
|
||||
import { useFumadocsLoader } from 'fumadocs-core/source/client';
|
||||
import { useMDXComponents } from '@/components/mdx';
|
||||
|
||||
export async function loader({ params }: Route.LoaderArgs) {
|
||||
const slugs = params['*'].split('/').filter((v) => v.length > 0);
|
||||
const page = source.getPage(slugs);
|
||||
if (!page) throw new Response('Not found', { status: 404 });
|
||||
|
||||
return {
|
||||
slugs: page.slugs,
|
||||
path: page.path,
|
||||
pageTree: await source.serializePageTree(source.getPageTree()),
|
||||
};
|
||||
}
|
||||
|
||||
const clientLoader = browserCollections.docs.createClientLoader({
|
||||
component(
|
||||
{ toc, frontmatter, default: Mdx },
|
||||
// you can define props for the component
|
||||
{
|
||||
markdownUrl,
|
||||
path,
|
||||
}: {
|
||||
markdownUrl: string;
|
||||
path: string;
|
||||
},
|
||||
) {
|
||||
return (
|
||||
<DocsPage toc={toc}>
|
||||
<title>{frontmatter.title}</title>
|
||||
<meta name="description" content={frontmatter.description} />
|
||||
<DocsTitle>{frontmatter.title}</DocsTitle>
|
||||
<DocsDescription>{frontmatter.description}</DocsDescription>
|
||||
<div className="flex flex-row gap-2 items-center border-b -mt-4 pb-6">
|
||||
<MarkdownCopyButton markdownUrl={markdownUrl} />
|
||||
<ViewOptionsPopover
|
||||
markdownUrl={markdownUrl}
|
||||
githubUrl={`https://github.com/${gitConfig.user}/${gitConfig.repo}/blob/${gitConfig.branch}/content/docs/${path}`}
|
||||
/>
|
||||
</div>
|
||||
<DocsBody>
|
||||
<Mdx components={useMDXComponents()} />
|
||||
</DocsBody>
|
||||
</DocsPage>
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
export default function Page({ loaderData }: Route.ComponentProps) {
|
||||
const { pageTree, slugs, path } = useFumadocsLoader(loaderData);
|
||||
const markdownUrl = `/llms.mdx/docs/${[...slugs, 'index.mdx'].join('/')}`;
|
||||
|
||||
return (
|
||||
<DocsLayout {...baseOptions()} tree={pageTree}>
|
||||
{clientLoader.useContent(loaderData.path, {
|
||||
markdownUrl,
|
||||
path,
|
||||
})}
|
||||
</DocsLayout>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
import type { Route } from './+types/home';
|
||||
import { HomeLayout } from 'fumadocs-ui/layouts/home';
|
||||
import { Link } from 'react-router';
|
||||
import { baseOptions } from '@/lib/layout.shared';
|
||||
|
||||
export function meta({}: Route.MetaArgs) {
|
||||
return [
|
||||
{ title: 'New React Router App' },
|
||||
{ name: 'description', content: 'Welcome to React Router!' },
|
||||
];
|
||||
}
|
||||
|
||||
export default function Home() {
|
||||
return (
|
||||
<HomeLayout {...baseOptions()}>
|
||||
<div className="p-4 flex flex-col items-center justify-center text-center flex-1">
|
||||
<h1 className="text-xl font-bold mb-2">Helix API Documentation</h1>
|
||||
<p className="text-fd-muted-foreground mb-4">
|
||||
Powered by Vite, React Router and Fumadocs OpenAPI.
|
||||
</p>
|
||||
<div className="flex items-center gap-3">
|
||||
<Link
|
||||
className="text-sm bg-fd-primary text-fd-primary-foreground rounded-full font-medium px-4 py-2.5"
|
||||
to="/api-reference"
|
||||
>
|
||||
Open API Reference
|
||||
</Link>
|
||||
<Link className="text-sm rounded-full font-medium px-4 py-2.5 border" to="/docs">
|
||||
Open MDX Docs
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</HomeLayout>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
import type { Route } from './+types/not-found';
|
||||
import { HomeLayout } from 'fumadocs-ui/layouts/home';
|
||||
import { Link } from 'react-router';
|
||||
import { baseOptions } from '@/lib/layout.shared';
|
||||
|
||||
export function meta({}: Route.MetaArgs) {
|
||||
return [{ title: 'Not Found' }];
|
||||
}
|
||||
|
||||
export default function NotFound() {
|
||||
return (
|
||||
<HomeLayout {...baseOptions()}>
|
||||
<div className="p-4 flex flex-col items-center justify-center text-center flex-1">
|
||||
<h1 className="text-xl font-bold mb-2">Not Found</h1>
|
||||
<p className="text-fd-muted-foreground mb-4">This page could not be found.</p>
|
||||
<Link
|
||||
className="text-sm bg-fd-primary text-fd-primary-foreground rounded-full font-medium px-4 py-2.5"
|
||||
to="/docs"
|
||||
>
|
||||
Back to Docs
|
||||
</Link>
|
||||
</div>
|
||||
</HomeLayout>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
import { createFromSource } from 'fumadocs-core/search/server';
|
||||
import { source } from '@/lib/source';
|
||||
|
||||
const server = createFromSource(source, {
|
||||
language: 'english',
|
||||
});
|
||||
|
||||
export async function loader() {
|
||||
return server.staticGET();
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
---
|
||||
title: Hello World
|
||||
description: |
|
||||
Your first `document`
|
||||
You'll love it!
|
||||
---
|
||||
|
||||
Hey there! Fumadocs is the docs framework that also works on React Router!
|
||||
|
||||
## Heading
|
||||
|
||||
Hello World
|
||||
|
||||
<Cards>
|
||||
<Card title="Learn more about React Router" href="https://reactrouter.com" />
|
||||
<Card title="Learn more about Fumadocs" href="https://fumadocs.dev" />
|
||||
</Cards>
|
||||
|
||||
```ts
|
||||
console.log('I love React!');
|
||||
```
|
||||
|
||||
### Heading
|
||||
|
||||
#### Heading
|
||||
|
||||
| Head | Description |
|
||||
| ------------------------------- | ----------------------------------- |
|
||||
| `hello` | Hello World |
|
||||
| very **important** | Hey |
|
||||
| _Surprisingly_ | Fumadocs |
|
||||
| very long text that looks weird | hello world hello world hello world |
|
||||
@@ -0,0 +1,24 @@
|
||||
---
|
||||
title: Test
|
||||
description: A document to test Fumadocs
|
||||
---
|
||||
|
||||
Hey there!
|
||||
|
||||
## Cards
|
||||
|
||||
<Cards>
|
||||
<Card title="Learn more about Next.js" href="https://nextjs.org/docs" />
|
||||
<Card title="Learn more about Fumadocs" href="https://fumadocs.dev" />
|
||||
</Cards>
|
||||
|
||||
### CodeBlock
|
||||
|
||||
```js
|
||||
console.log('Hello World');
|
||||
```
|
||||
|
||||
#### List
|
||||
|
||||
- Hello
|
||||
- World
|
||||
@@ -0,0 +1,32 @@
|
||||
openapi: 3.1.0
|
||||
info:
|
||||
title: Helix API
|
||||
version: 0.1.0
|
||||
description: |
|
||||
Initial OpenAPI skeleton.
|
||||
Maintain this file manually.
|
||||
servers:
|
||||
- url: http://localhost:5000
|
||||
description: Local development
|
||||
paths:
|
||||
/health:
|
||||
get:
|
||||
summary: Health check
|
||||
operationId: healthCheck
|
||||
tags:
|
||||
- System
|
||||
responses:
|
||||
'200':
|
||||
description: Service is available
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
status:
|
||||
type: string
|
||||
example: ok
|
||||
required:
|
||||
- status
|
||||
components:
|
||||
securitySchemes: {}
|
||||
@@ -0,0 +1,39 @@
|
||||
{
|
||||
"name": "docs",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"build": "react-router build",
|
||||
"dev": "react-router dev",
|
||||
"start": "serve ./build/client --config ../../serve.json",
|
||||
"types:check": "react-router typegen && fumadocs-mdx && tsc --noEmit",
|
||||
"postinstall": "fumadocs-mdx"
|
||||
},
|
||||
"dependencies": {
|
||||
"@orama/orama": "^3.1.18",
|
||||
"@react-router/node": "^7.13.1",
|
||||
"fumadocs-core": "16.7.5",
|
||||
"fumadocs-mdx": "14.2.11",
|
||||
"fumadocs-openapi": "^10.4.1",
|
||||
"fumadocs-ui": "16.7.5",
|
||||
"isbot": "^5.1.36",
|
||||
"lucide-react": "^0.577.0",
|
||||
"react": "^19.2.4",
|
||||
"react-dom": "^19.2.4",
|
||||
"react-router": "^7.13.1",
|
||||
"tailwind-merge": "^3.5.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@react-router/dev": "^7.13.1",
|
||||
"@tailwindcss/vite": "^4.2.2",
|
||||
"@types/mdx": "^2.0.13",
|
||||
"@types/node": "^25.5.0",
|
||||
"@types/react": "^19.2.14",
|
||||
"@types/react-dom": "^19.2.3",
|
||||
"react-router-devtools": "^6.2.0",
|
||||
"serve": "^14.2.6",
|
||||
"tailwindcss": "^4.2.2",
|
||||
"typescript": "^5.9.3",
|
||||
"vite": "^8.0.1"
|
||||
}
|
||||
}
|
||||
Generated
+6401
File diff suppressed because it is too large.
Load diff
Binary file not shown.
|
After Width: | Height: | Size: 15 KiB |
@@ -0,0 +1,27 @@
|
||||
import type { Config } from '@react-router/dev/config';
|
||||
import { glob } from 'node:fs/promises';
|
||||
import { createGetUrl, getSlugs } from 'fumadocs-core/source';
|
||||
|
||||
const getUrl = createGetUrl('/docs');
|
||||
|
||||
export default {
|
||||
ssr: false,
|
||||
future: {
|
||||
v8_middleware: true,
|
||||
},
|
||||
async prerender({ getStaticPaths }) {
|
||||
const paths: string[] = [];
|
||||
const excluded: string[] = ['/api-reference', '/api-reference/'];
|
||||
|
||||
for (const path of getStaticPaths()) {
|
||||
if (!excluded.includes(path)) paths.push(path);
|
||||
}
|
||||
|
||||
for await (const entry of glob('**/*.mdx', { cwd: 'content/docs' })) {
|
||||
const slugs = getSlugs(entry);
|
||||
paths.push(getUrl(slugs), `/llms.mdx/docs/${[...slugs, 'index.mdx'].join('/')}`);
|
||||
}
|
||||
|
||||
return paths;
|
||||
},
|
||||
} satisfies Config;
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"rewrites": [{ "source": "/**", "destination": "/__spa-fallback.html" }]
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import { defineConfig, defineDocs } from 'fumadocs-mdx/config';
|
||||
|
||||
export const docs = defineDocs({
|
||||
dir: 'content/docs',
|
||||
docs: {
|
||||
postprocess: {
|
||||
includeProcessedMarkdown: true,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
export default defineConfig();
|
||||
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"include": ["**/*", "**/.server/**/*", "**/.client/**/*", ".react-router/types/**/*"],
|
||||
"compilerOptions": {
|
||||
"lib": ["DOM", "DOM.Iterable", "ES2022"],
|
||||
"types": ["node", "vite/client"],
|
||||
"target": "esnext",
|
||||
"module": "esnext",
|
||||
"moduleResolution": "bundler",
|
||||
"jsx": "react-jsx",
|
||||
"rootDirs": [".", "./.react-router/types"],
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"@/*": ["./app/*"],
|
||||
"collections/*": [".source/*"]
|
||||
},
|
||||
"esModuleInterop": true,
|
||||
"verbatimModuleSyntax": true,
|
||||
"noEmit": true,
|
||||
"resolveJsonModule": true,
|
||||
"skipLibCheck": true,
|
||||
"strict": true
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import { reactRouter } from '@react-router/dev/vite';
|
||||
import tailwindcss from '@tailwindcss/vite';
|
||||
import { defineConfig } from 'vite';
|
||||
import mdx from 'fumadocs-mdx/vite';
|
||||
import * as MdxConfig from './source.config';
|
||||
|
||||
export default defineConfig({
|
||||
plugins: [mdx(MdxConfig), tailwindcss(), reactRouter()],
|
||||
resolve: {
|
||||
tsconfigPaths: true,
|
||||
},
|
||||
});
|
||||
Reference in new issue
Block a user