@raystack/chronicle 0.3.0 → 0.4.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.
Files changed (83) hide show
  1. package/dist/cli/index.js +289 -9931
  2. package/package.json +20 -12
  3. package/src/cli/commands/build.ts +28 -31
  4. package/src/cli/commands/dev.ts +24 -31
  5. package/src/cli/commands/init.ts +38 -132
  6. package/src/cli/commands/serve.ts +36 -55
  7. package/src/cli/commands/start.ts +20 -31
  8. package/src/cli/index.ts +14 -14
  9. package/src/cli/utils/config.ts +25 -26
  10. package/src/cli/utils/index.ts +3 -3
  11. package/src/cli/utils/resolve.ts +7 -3
  12. package/src/cli/utils/scaffold.ts +11 -130
  13. package/src/components/mdx/code.tsx +10 -1
  14. package/src/components/mdx/details.module.css +1 -26
  15. package/src/components/mdx/details.tsx +2 -3
  16. package/src/components/mdx/image.tsx +5 -34
  17. package/src/components/mdx/index.tsx +15 -1
  18. package/src/components/mdx/link.tsx +18 -15
  19. package/src/components/ui/breadcrumbs.tsx +8 -42
  20. package/src/components/ui/search.tsx +63 -51
  21. package/src/lib/api-routes.ts +6 -8
  22. package/src/lib/config.ts +12 -36
  23. package/src/lib/head.tsx +49 -0
  24. package/src/lib/openapi.ts +8 -8
  25. package/src/lib/page-context.tsx +111 -0
  26. package/src/lib/remark-strip-md-extensions.ts +14 -0
  27. package/src/lib/source.ts +139 -63
  28. package/src/pages/ApiLayout.tsx +33 -0
  29. package/src/pages/ApiPage.tsx +73 -0
  30. package/src/pages/DocsLayout.tsx +18 -0
  31. package/src/pages/DocsPage.tsx +43 -0
  32. package/src/pages/NotFound.tsx +17 -0
  33. package/src/server/App.tsx +72 -0
  34. package/src/server/api/apis-proxy.ts +69 -0
  35. package/src/server/api/health.ts +5 -0
  36. package/src/server/api/page/[...slug].ts +18 -0
  37. package/src/server/api/search.ts +118 -0
  38. package/src/server/api/specs.ts +9 -0
  39. package/src/server/build-search-index.ts +117 -0
  40. package/src/server/entry-client.tsx +88 -0
  41. package/src/server/entry-server.tsx +102 -0
  42. package/src/server/routes/llms.txt.ts +21 -0
  43. package/src/server/routes/og.tsx +75 -0
  44. package/src/server/routes/robots.txt.ts +11 -0
  45. package/src/server/routes/sitemap.xml.ts +40 -0
  46. package/src/server/utils/safe-path.ts +17 -0
  47. package/src/server/vite-config.ts +129 -0
  48. package/src/themes/default/Layout.tsx +78 -48
  49. package/src/themes/default/Page.module.css +44 -0
  50. package/src/themes/default/Page.tsx +9 -11
  51. package/src/themes/default/Toc.tsx +25 -39
  52. package/src/themes/default/index.ts +7 -9
  53. package/src/themes/paper/ChapterNav.tsx +64 -45
  54. package/src/themes/paper/Layout.module.css +1 -1
  55. package/src/themes/paper/Layout.tsx +24 -12
  56. package/src/themes/paper/Page.module.css +16 -4
  57. package/src/themes/paper/Page.tsx +56 -63
  58. package/src/themes/paper/ReadingProgress.tsx +160 -139
  59. package/src/themes/paper/index.ts +5 -5
  60. package/src/themes/registry.ts +14 -7
  61. package/src/types/content.ts +5 -21
  62. package/src/types/globals.d.ts +4 -0
  63. package/src/types/theme.ts +4 -3
  64. package/tsconfig.json +2 -3
  65. package/next.config.mjs +0 -10
  66. package/source.config.ts +0 -51
  67. package/src/app/[[...slug]]/layout.tsx +0 -15
  68. package/src/app/[[...slug]]/page.tsx +0 -106
  69. package/src/app/api/apis-proxy/route.ts +0 -59
  70. package/src/app/api/health/route.ts +0 -3
  71. package/src/app/api/search/route.ts +0 -90
  72. package/src/app/apis/[[...slug]]/layout.tsx +0 -26
  73. package/src/app/apis/[[...slug]]/page.tsx +0 -117
  74. package/src/app/layout.tsx +0 -57
  75. package/src/app/llms-full.txt/route.ts +0 -18
  76. package/src/app/llms.txt/route.ts +0 -15
  77. package/src/app/og/route.tsx +0 -62
  78. package/src/app/providers.tsx +0 -8
  79. package/src/app/robots.ts +0 -10
  80. package/src/app/sitemap.ts +0 -29
  81. package/src/cli/utils/process.ts +0 -7
  82. package/src/themes/default/font.ts +0 -6
  83. /package/src/{app/apis/[[...slug]]/layout.module.css → pages/ApiLayout.module.css} +0 -0
@@ -1,14 +1,21 @@
1
- import type { Theme } from '@/types'
2
- import { defaultTheme } from './default'
3
- import { paperTheme } from './paper'
1
+ import type { Theme } from '@/types';
2
+ import { defaultTheme } from './default';
3
+ import { paperTheme } from './paper';
4
4
 
5
5
  const themes: Record<string, Theme> = {
6
6
  default: defaultTheme,
7
- paper: paperTheme,
8
- }
7
+ paper: paperTheme
8
+ };
9
9
 
10
10
  export function getTheme(name?: string): Theme {
11
- if (!name || !themes[name]) return defaultTheme
11
+ if (!name || !themes[name]) return defaultTheme;
12
+
13
+ return themes[name];
14
+ }
12
15
 
13
- return themes[name]
16
+ export function getThemeConfig(name?: string) {
17
+ if (name === 'paper') {
18
+ return { enableSystem: false, forcedTheme: 'light' };
19
+ }
20
+ return { enableSystem: true };
14
21
  }
@@ -1,4 +1,8 @@
1
1
  import type { ReactNode } from 'react'
2
+ import type { TableOfContents } from 'fumadocs-core/toc'
3
+
4
+ export type { Root, Node, Item, Folder, Separator } from 'fumadocs-core/page-tree'
5
+ export type { TOCItemType, TableOfContents } from 'fumadocs-core/toc'
2
6
 
3
7
  export interface Frontmatter {
4
8
  title: string
@@ -12,25 +16,5 @@ export interface Page {
12
16
  slug: string[]
13
17
  frontmatter: Frontmatter
14
18
  content: ReactNode
15
- toc: TocItem[]
16
- }
17
-
18
- export interface TocItem {
19
- title: string
20
- url: string
21
- depth: number
22
- }
23
-
24
- export interface PageTreeItem {
25
- type: 'page' | 'folder' | 'separator'
26
- name: string
27
- url?: string
28
- order?: number
29
- icon?: string
30
- children?: PageTreeItem[]
31
- }
32
-
33
- export interface PageTree {
34
- name: string
35
- children: PageTreeItem[]
19
+ toc: TableOfContents
36
20
  }
@@ -0,0 +1,4 @@
1
+ // Vite build-time constants (injected via define in vite-config.ts)
2
+ declare const __CHRONICLE_CONTENT_DIR__: string
3
+ declare const __CHRONICLE_PROJECT_ROOT__: string
4
+ declare const __CHRONICLE_CONFIG_RAW__: string | null
@@ -1,18 +1,19 @@
1
1
  import type { ReactNode } from 'react'
2
+ import type { Root } from 'fumadocs-core/page-tree'
2
3
  import type { ChronicleConfig } from './config'
3
- import type { Page, PageTree } from './content'
4
+ import type { Page } from './content'
4
5
 
5
6
  export interface ThemeLayoutProps {
6
7
  children: ReactNode
7
8
  config: ChronicleConfig
8
- tree: PageTree
9
+ tree: Root
9
10
  classNames?: { layout?: string; body?: string; sidebar?: string; content?: string }
10
11
  }
11
12
 
12
13
  export interface ThemePageProps {
13
14
  page: Page
14
15
  config: ChronicleConfig
15
- tree: PageTree
16
+ tree: Root
16
17
  }
17
18
 
18
19
  export interface Theme {
package/tsconfig.json CHANGED
@@ -21,10 +21,9 @@
21
21
  "lib": ["ES2022", "DOM", "DOM.Iterable"],
22
22
  "moduleResolution": "bundler",
23
23
  "paths": {
24
- "@/*": ["./src/*"],
25
- "@/.source/*": ["./.source/*"]
24
+ "@/*": ["./src/*"]
26
25
  }
27
26
  },
28
- "include": ["src", ".source", "source.config.ts"],
27
+ "include": ["src"],
29
28
  "exclude": ["node_modules", "dist"]
30
29
  }
package/next.config.mjs DELETED
@@ -1,10 +0,0 @@
1
- import { createMDX } from 'fumadocs-mdx/next'
2
-
3
- const withMDX = createMDX()
4
-
5
- /** @type {import('next').NextConfig} */
6
- const nextConfig = {
7
- reactStrictMode: true,
8
- }
9
-
10
- export default withMDX(nextConfig)
package/source.config.ts DELETED
@@ -1,51 +0,0 @@
1
- import { defineDocs, defineConfig, frontmatterSchema } from 'fumadocs-mdx/config'
2
- import { z } from 'zod'
3
- import remarkDirective from 'remark-directive'
4
- import { remarkDirectiveAdmonition, remarkMdxMermaid } from 'fumadocs-core/mdx-plugins'
5
- import remarkUnusedDirectives from './src/lib/remark-unused-directives'
6
-
7
- const contentDir = process.env.CHRONICLE_CONTENT_DIR || './content'
8
-
9
- export const docs = defineDocs({
10
- dir: contentDir,
11
- docs: {
12
- schema: frontmatterSchema.extend({
13
- order: z.number().optional(),
14
- lastModified: z.string().optional(),
15
- }),
16
- postprocess: {
17
- includeProcessedMarkdown: true,
18
- },
19
- files: ['**/*.mdx', '**/*.md', '!**/node_modules/**'],
20
- },
21
- })
22
-
23
- export default defineConfig({
24
- mdxOptions: {
25
- remarkPlugins: [
26
- remarkDirective,
27
- [
28
- remarkDirectiveAdmonition,
29
- {
30
- tags: {
31
- CalloutContainer: 'Callout',
32
- CalloutTitle: 'CalloutTitle',
33
- CalloutDescription: 'CalloutDescription',
34
- },
35
- types: {
36
- note: 'accent',
37
- tip: 'accent',
38
- info: 'accent',
39
- warn: 'attention',
40
- warning: 'attention',
41
- danger: 'alert',
42
- caution: 'alert',
43
- success: 'success',
44
- },
45
- },
46
- ],
47
- remarkUnusedDirectives,
48
- remarkMdxMermaid,
49
- ],
50
- },
51
- })
@@ -1,15 +0,0 @@
1
- import { loadConfig } from '@/lib/config'
2
- import { buildPageTree } from '@/lib/source'
3
- import { getTheme } from '@/themes/registry'
4
-
5
- export default function DocsLayout({ children }: { children: React.ReactNode }) {
6
- const config = loadConfig()
7
- const tree = buildPageTree()
8
- const { Layout, className } = getTheme(config.theme?.name)
9
-
10
- return (
11
- <Layout config={config} tree={tree} classNames={{ layout: className }}>
12
- {children}
13
- </Layout>
14
- )
15
- }
@@ -1,106 +0,0 @@
1
- import type { Metadata, ResolvingMetadata } from 'next'
2
- import { notFound } from 'next/navigation'
3
- import type { MDXContent } from 'mdx/types'
4
- import { loadConfig } from '@/lib/config'
5
- import { source, buildPageTree } from '@/lib/source'
6
- import { getTheme } from '@/themes/registry'
7
- import { mdxComponents } from '@/components/mdx'
8
-
9
- interface PageProps {
10
- params: Promise<{ slug?: string[] }>
11
- }
12
-
13
- interface PageData {
14
- title: string
15
- description?: string
16
- body: MDXContent
17
- toc: { title: string; url: string; depth: number }[]
18
- }
19
-
20
- export async function generateMetadata(
21
- { params }: PageProps,
22
- parent: ResolvingMetadata,
23
- ): Promise<Metadata> {
24
- const { slug } = await params
25
- const page = source.getPage(slug)
26
- if (!page) return {}
27
- const config = loadConfig()
28
- const data = page.data as PageData
29
- const parentMetadata = await parent
30
-
31
- const metadata: Metadata = {
32
- title: data.title,
33
- description: data.description,
34
- }
35
-
36
- if (config.url) {
37
- const ogParams = new URLSearchParams({ title: data.title })
38
- if (data.description) ogParams.set('description', data.description)
39
- metadata.openGraph = {
40
- ...parentMetadata.openGraph,
41
- title: data.title,
42
- description: data.description,
43
- images: [{ url: `/og?${ogParams.toString()}`, width: 1200, height: 630 }],
44
- }
45
- metadata.twitter = {
46
- ...parentMetadata.twitter,
47
- title: data.title,
48
- description: data.description,
49
- }
50
- }
51
-
52
- return metadata
53
- }
54
-
55
- export default async function DocsPage({ params }: PageProps) {
56
- const { slug } = await params
57
- const config = loadConfig()
58
-
59
- const page = source.getPage(slug)
60
-
61
- if (!page) {
62
- notFound()
63
- }
64
-
65
- const { Page } = getTheme(config.theme?.name)
66
-
67
- const data = page.data as PageData
68
- const MDXBody = data.body
69
-
70
- const tree = buildPageTree()
71
-
72
- const pageUrl = config.url ? `${config.url}/${(slug ?? []).join('/')}` : undefined
73
-
74
- return (
75
- <>
76
- <script type="application/ld+json">
77
- {JSON.stringify({
78
- '@context': 'https://schema.org',
79
- '@type': 'Article',
80
- headline: data.title,
81
- description: data.description,
82
- ...(pageUrl && { url: pageUrl }),
83
- }, null, 2)}
84
- </script>
85
- <Page
86
- page={{
87
- slug: slug ?? [],
88
- frontmatter: {
89
- title: data.title,
90
- description: data.description,
91
- },
92
- content: <MDXBody components={mdxComponents} />,
93
- toc: data.toc ?? [],
94
- }}
95
- config={config}
96
- tree={tree}
97
- />
98
- </>
99
- )
100
- }
101
-
102
- export function generateStaticParams() {
103
- return source.getPages().map((page) => ({
104
- slug: page.slugs,
105
- }))
106
- }
@@ -1,59 +0,0 @@
1
- import { NextRequest, NextResponse } from "next/server";
2
- import { loadConfig } from "@/lib/config";
3
- import { loadApiSpecs } from "@/lib/openapi";
4
-
5
- export async function POST(request: NextRequest) {
6
- const { specName, method, path, headers, body } = await request.json();
7
-
8
- if (!specName || !method || !path) {
9
- return NextResponse.json(
10
- { error: "Missing specName, method, or path" },
11
- { status: 400 },
12
- );
13
- }
14
-
15
- const config = loadConfig();
16
- const specs = loadApiSpecs(config.api ?? []);
17
- const spec = specs.find((s) => s.name === specName);
18
-
19
- if (!spec) {
20
- return NextResponse.json(
21
- { error: `Unknown spec: ${specName}` },
22
- { status: 404 },
23
- );
24
- }
25
-
26
- const url = spec.server.url + path;
27
-
28
- try {
29
- const response = await fetch(url, {
30
- method,
31
- headers,
32
- body: body ? JSON.stringify(body) : undefined,
33
- });
34
-
35
- const contentType = response.headers.get("content-type") ?? "";
36
- const responseBody = contentType.includes("application/json")
37
- ? await response.json()
38
- : await response.text();
39
-
40
- return NextResponse.json({
41
- status: response.status,
42
- statusText: response.statusText,
43
- body: responseBody,
44
- }, { status: response.status });
45
- } catch (error) {
46
- const message =
47
- error instanceof Error
48
- ? `${error.message}${error.cause ? `: ${(error.cause as Error).message}` : ""}`
49
- : "Request failed";
50
- return NextResponse.json(
51
- {
52
- status: 502,
53
- statusText: "Bad Gateway",
54
- body: `Could not reach ${url}\n${message}`,
55
- },
56
- { status: 502 },
57
- );
58
- }
59
- }
@@ -1,3 +0,0 @@
1
- export function GET() {
2
- return Response.json({ status: 'ok' })
3
- }
@@ -1,90 +0,0 @@
1
- import { source } from '@/lib/source'
2
- import { createSearchAPI, type AdvancedIndex } from 'fumadocs-core/search/server'
3
- import type { StructuredData } from 'fumadocs-core/mdx-plugins'
4
- import type { OpenAPIV3 } from 'openapi-types'
5
- import { loadConfig } from '@/lib/config'
6
- import { loadApiSpecs, type ApiSpec } from '@/lib/openapi'
7
- import { getSpecSlug } from '@/lib/api-routes'
8
-
9
- interface PageData {
10
- title?: string
11
- description?: string
12
- structuredData?: StructuredData
13
- load?: () => Promise<{ structuredData?: StructuredData }>
14
- }
15
-
16
- const HTTP_METHODS = ['get', 'post', 'put', 'delete', 'patch'] as const
17
- type HttpMethod = (typeof HTTP_METHODS)[number]
18
-
19
- function getParamNames(op: OpenAPIV3.OperationObject): string[] {
20
- const params = (op.parameters as OpenAPIV3.ParameterObject[] | undefined) ?? []
21
- return params.map((p) => p.name)
22
- }
23
-
24
- function buildStructuredData(op: OpenAPIV3.OperationObject, method: string, pathStr: string) {
25
- return {
26
- headings: [{ id: op.operationId!, content: `${method.toUpperCase()} ${pathStr}` }],
27
- contents: [{ heading: op.operationId!, content: `${method.toUpperCase()} ${[op.description, ...getParamNames(op)].filter(Boolean).join(' ')}` }],
28
- }
29
- }
30
-
31
- function operationToIndex(specSlug: string, pathStr: string, method: HttpMethod, op: OpenAPIV3.OperationObject): AdvancedIndex {
32
- const url = `/apis/${specSlug}/${encodeURIComponent(op.operationId!)}`
33
- return {
34
- id: url,
35
- url,
36
- title: `${method.toUpperCase()} ${op.summary ?? op.operationId!}`,
37
- description: op.description ?? '',
38
- structuredData: buildStructuredData(op, method, pathStr),
39
- }
40
- }
41
-
42
- function pathEntryToIndexes(specSlug: string) {
43
- return ([pathStr, pathItem]: [string, OpenAPIV3.PathItemObject | undefined]): AdvancedIndex[] => {
44
- if (!pathItem) return []
45
- const hasOp = (m: HttpMethod) => !!pathItem[m]?.operationId
46
- const toIndex = (m: HttpMethod) => operationToIndex(specSlug, pathStr, m, pathItem[m]!)
47
- return HTTP_METHODS.filter(hasOp).map(toIndex)
48
- }
49
- }
50
-
51
- function specToIndexes(spec: ApiSpec): AdvancedIndex[] {
52
- const specSlug = getSpecSlug(spec)
53
- return Object.entries(spec.document.paths ?? {}).flatMap(pathEntryToIndexes(specSlug))
54
- }
55
-
56
- function buildApiIndexes(): AdvancedIndex[] {
57
- const config = loadConfig()
58
- if (!config.api?.length) return []
59
- return loadApiSpecs(config.api).flatMap(specToIndexes)
60
- }
61
-
62
- export const { GET } = createSearchAPI('advanced', {
63
- indexes: async (): Promise<AdvancedIndex[]> => {
64
- const pages = source.getPages()
65
- const indexes = await Promise.all(
66
- pages.map(async (page): Promise<AdvancedIndex> => {
67
- const data = page.data as PageData
68
- let structuredData: StructuredData | undefined = data.structuredData
69
-
70
- if (!structuredData && data.load) {
71
- try {
72
- const loaded = await data.load()
73
- structuredData = loaded.structuredData
74
- } catch (error) {
75
- console.error(`Failed to load structured data for ${page.url}:`, error)
76
- }
77
- }
78
-
79
- return {
80
- id: page.url,
81
- url: page.url,
82
- title: data.title ?? '',
83
- description: data.description ?? '',
84
- structuredData: structuredData ?? { headings: [], contents: [] },
85
- }
86
- })
87
- )
88
- return [...indexes, ...buildApiIndexes()]
89
- },
90
- })
@@ -1,26 +0,0 @@
1
- import { cx } from 'class-variance-authority'
2
- import { loadConfig } from '@/lib/config'
3
- import { loadApiSpecs } from '@/lib/openapi'
4
- import { buildApiPageTree } from '@/lib/api-routes'
5
- import { getTheme } from '@/themes/registry'
6
- import { Search } from '@/components/ui/search'
7
- import styles from './layout.module.css'
8
-
9
- export default function ApiLayout({ children }: { children: React.ReactNode }) {
10
- const config = loadConfig()
11
- const { Layout, className } = getTheme(config.theme?.name)
12
- const specs = loadApiSpecs(config.api ?? [])
13
- const tree = buildApiPageTree(specs)
14
-
15
- return (
16
- <Layout config={config} tree={tree} classNames={{
17
- layout: cx(styles.layout, className),
18
- body: styles.body,
19
- sidebar: styles.sidebar,
20
- content: styles.content,
21
- }}>
22
- <Search className={styles.hiddenSearch} />
23
- {children}
24
- </Layout>
25
- )
26
- }
@@ -1,117 +0,0 @@
1
- import type { Metadata, ResolvingMetadata } from 'next'
2
- import { notFound } from 'next/navigation'
3
- import type { OpenAPIV3 } from 'openapi-types'
4
- import { Flex, Headline, Text } from '@raystack/apsara'
5
- import { loadConfig } from '@/lib/config'
6
- import { loadApiSpecs } from '@/lib/openapi'
7
- import { buildApiRoutes, findApiOperation } from '@/lib/api-routes'
8
- import { EndpointPage } from '@/components/api'
9
-
10
- interface PageProps {
11
- params: Promise<{ slug?: string[] }>
12
- }
13
-
14
- export async function generateMetadata(
15
- { params }: PageProps,
16
- parent: ResolvingMetadata,
17
- ): Promise<Metadata> {
18
- const { slug } = await params
19
- const config = loadConfig()
20
- const specs = loadApiSpecs(config.api ?? [])
21
- const parentMetadata = await parent
22
-
23
- if (!slug || slug.length === 0) {
24
- const apiDescription = `API documentation for ${config.title}`
25
- const metadata: Metadata = {
26
- title: 'API Reference',
27
- description: apiDescription,
28
- }
29
- if (config.url) {
30
- metadata.openGraph = {
31
- ...parentMetadata.openGraph,
32
- title: 'API Reference',
33
- description: apiDescription,
34
- images: [{ url: `/og?title=${encodeURIComponent('API Reference')}&description=${encodeURIComponent(apiDescription)}`, width: 1200, height: 630 }],
35
- }
36
- metadata.twitter = {
37
- ...parentMetadata.twitter,
38
- title: 'API Reference',
39
- description: apiDescription,
40
- }
41
- }
42
- return metadata
43
- }
44
-
45
- const match = findApiOperation(specs, slug)
46
- if (!match) return {}
47
-
48
- const operation = match.operation as OpenAPIV3.OperationObject
49
- const title = operation.summary ?? `${match.method.toUpperCase()} ${match.path}`
50
- const description = operation.description
51
-
52
- const metadata: Metadata = { title, description }
53
-
54
- if (config.url) {
55
- const ogParams = new URLSearchParams({ title })
56
- if (description) ogParams.set('description', description)
57
- metadata.openGraph = {
58
- ...parentMetadata.openGraph,
59
- title,
60
- description,
61
- images: [{ url: `/og?${ogParams.toString()}`, width: 1200, height: 630 }],
62
- }
63
- metadata.twitter = {
64
- ...parentMetadata.twitter,
65
- title,
66
- description,
67
- }
68
- }
69
-
70
- return metadata
71
- }
72
-
73
- export default async function ApiPage({ params }: PageProps) {
74
- const { slug } = await params
75
- const config = loadConfig()
76
- const specs = loadApiSpecs(config.api ?? [])
77
-
78
- if (!slug || slug.length === 0) {
79
- return <ApiLanding specs={specs} />
80
- }
81
-
82
- const match = findApiOperation(specs, slug)
83
- if (!match) notFound()
84
-
85
- return (
86
- <EndpointPage
87
- method={match.method}
88
- path={match.path}
89
- operation={match.operation}
90
- serverUrl={match.spec.server.url}
91
- specName={match.spec.name}
92
- auth={match.spec.auth}
93
- />
94
- )
95
- }
96
-
97
- function ApiLanding({ specs }: { specs: { name: string; document: OpenAPIV3.Document }[] }) {
98
- return (
99
- <Flex direction="column" gap="large" style={{ padding: 'var(--rs-space-7)' }}>
100
- <Headline size="medium" as="h1">API Reference</Headline>
101
- {specs.map((spec) => (
102
- <Flex key={spec.name} direction="column" gap="small">
103
- <Headline size="small" as="h2">{spec.name}</Headline>
104
- {spec.document.info.description && (
105
- <Text size={3}>{spec.document.info.description}</Text>
106
- )}
107
- </Flex>
108
- ))}
109
- </Flex>
110
- )
111
- }
112
-
113
- export function generateStaticParams() {
114
- const config = loadConfig()
115
- const specs = loadApiSpecs(config.api ?? [])
116
- return [{ slug: [] }, ...buildApiRoutes(specs)]
117
- }
@@ -1,57 +0,0 @@
1
- import '@raystack/apsara/normalize.css'
2
- import '@raystack/apsara/style.css'
3
- import type { Metadata } from 'next'
4
- import { loadConfig } from '@/lib/config'
5
- import { Providers } from './providers'
6
-
7
- const config = loadConfig()
8
-
9
- export const metadata: Metadata = {
10
- title: {
11
- default: config.title,
12
- template: `%s | ${config.title}`,
13
- },
14
- description: config.description,
15
- ...(config.url && {
16
- metadataBase: new URL(config.url),
17
- openGraph: {
18
- title: config.title,
19
- description: config.description,
20
- url: config.url,
21
- siteName: config.title,
22
- type: 'website',
23
- images: [{ url: '/og?title=' + encodeURIComponent(config.title), width: 1200, height: 630 }],
24
- },
25
- twitter: {
26
- card: 'summary_large_image',
27
- title: config.title,
28
- description: config.description,
29
- images: ['/og?title=' + encodeURIComponent(config.title)],
30
- },
31
- }),
32
- }
33
-
34
- export default function RootLayout({
35
- children,
36
- }: {
37
- children: React.ReactNode
38
- }) {
39
- return (
40
- <html lang="en" suppressHydrationWarning>
41
- <body suppressHydrationWarning>
42
- {config.url && (
43
- <script type="application/ld+json">
44
- {JSON.stringify({
45
- '@context': 'https://schema.org',
46
- '@type': 'WebSite',
47
- name: config.title,
48
- description: config.description,
49
- url: config.url,
50
- }, null, 2)}
51
- </script>
52
- )}
53
- <Providers>{children}</Providers>
54
- </body>
55
- </html>
56
- )
57
- }
@@ -1,18 +0,0 @@
1
- import { source } from '@/lib/source'
2
- import { loadConfig } from '@/lib/config'
3
- import { getLLMText } from '@/lib/get-llm-text'
4
-
5
- export const revalidate = false
6
-
7
- export async function GET() {
8
- const config = loadConfig()
9
-
10
- if (!config.llms?.enabled) {
11
- return new Response('Not Found', { status: 404 })
12
- }
13
-
14
- const scan = source.getPages().map(getLLMText)
15
- const scanned = await Promise.all(scan)
16
-
17
- return new Response(scanned.join('\n\n'))
18
- }
@@ -1,15 +0,0 @@
1
- import { source } from '@/lib/source'
2
- import { loadConfig } from '@/lib/config'
3
- import { llms } from 'fumadocs-core/source'
4
-
5
- export const revalidate = false
6
-
7
- export function GET() {
8
- const config = loadConfig()
9
-
10
- if (!config.llms?.enabled) {
11
- return new Response('Not Found', { status: 404 })
12
- }
13
-
14
- return new Response(llms(source).index())
15
- }