feat(library): serve agent-readable markdown for each docs page (#49567)

## I have read the
[CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md)
file.

YES

## What kind of change does this PR introduce?

Feature: agent-readable markdown pages for the UI library docs.

## What is the current behavior?

Library docs are HTML-only. `llms.txt` lists page titles, but there is
no `.md` body an agent can fetch.

## What is the new behavior?

Each docs page is also served as markdown:

- Build-time MDX → markdown (`pnpm --filter library build:markdown`)
- `GET /library/docs/{slug}.md` (and `Accept: text/markdown`)
- HTML pages advertise `rel=alternate` `text/markdown`
- `llms.txt` links to the `.md` URLs

This is the base of a stack. The prompt-tab PR sits on top:
https://github.com/supabase/supabase/pull/49566

## Additional context

Interactive previews are omitted from the markdown. `BlockItem` emits
the production `npx shadcn add` command so agents still get an install
path.

## To test

1. `pnpm --filter library dev` (generates markdown in `predev`).
2. Open http://localhost:3004/library/docs/nextjs/password-based-auth.md
— markdown with the install command, file tree, and setup steps; no
interactive previews.
3. Open the same path without `.md` — HTML docs unchanged (no prompt tab
in this PR).
4. `curl -H 'Accept: text/markdown'
http://localhost:3004/library/docs/nextjs/password-based-auth` should
also return markdown.
5. http://localhost:3004/library/llms.txt — links should end in `.md`.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Documentation pages are available as Markdown through `.md` URLs and a
dedicated endpoint.
* Markdown is generated automatically during development and production
builds.
* Generated content preserves front matter, links, callouts,
installation instructions, and supported documentation elements.
* Installation commands support npm, pnpm, yarn, and bun for React and
Vue projects.

* **Bug Fixes**
* Improved Markdown file handling, link rewriting, and content
negotiation.

* **Tests**
* Added coverage for Markdown conversion, content negotiation, and
installation commands.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Saxon Fletcher <SaxonF@users.noreply.github.com>
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
authored and GitHub committed 2026-09-01 11:35:55 +10:00
1 parent eea39cc316
commit bf60e6cdce
16 files changed
+717 -101

No files matched your search

+5 -1
View File
@@ -38,4 +38,8 @@ next-env.d.ts
.contentlayer
# Auto-generated on every Vercel build by `pnpm build:llms` -> scripts/build-llms-txt.ts
public/llms.txt
public/llms.txt
# Generated page markdown, including the slug allowlist imported by middleware.
# Regenerated by `pnpm build:markdown` during predev and build.
public/markdown/
@@ -41,10 +41,17 @@ export async function generateMetadata(props: DocPageProps): Promise<Metadata> {
return {}
}
const markdownPath = `${process.env.NEXT_PUBLIC_BASE_PATH ?? '/library'}/docs/${doc.slugAsParams}.md`
const metadata: Metadata = {
...mainMetadata,
title: doc.title,
description: doc.description,
alternates: {
types: {
'text/markdown': `https://supabase.com${markdownPath}`,
},
},
openGraph: {
...mainMetadata.openGraph,
title: doc.title,
@@ -0,0 +1,43 @@
import { promises as fs } from 'node:fs'
import path from 'node:path'
import { NextResponse } from 'next/server'
export async function GET(_request: Request, { params }: { params: Promise<{ slug: string[] }> }) {
const { slug } = await params
const baseDir = path.join(process.cwd(), 'public/markdown/docs')
const filePath = path.join(baseDir, `${slug.join('/')}.md`)
if (!filePath.startsWith(baseDir + path.sep) && filePath !== baseDir) {
return markdownNotFound(slug)
}
try {
const content = await fs.readFile(filePath, 'utf-8')
return new NextResponse(content, {
headers: {
'Content-Type': 'text/markdown; charset=utf-8',
'Cache-Control': 'public, max-age=86400, stale-while-revalidate=3600',
Vary: 'Accept',
},
})
} catch {
return markdownNotFound(slug)
}
}
function markdownNotFound(slug: string[]) {
const pagePath = slug.join('/')
const markdown = `# 404 - Page Not Found
The page \`/library/docs/${pagePath}.md\` does not exist.
See also: [Supabase Library](https://supabase.com/library/llms.txt)
`
return new NextResponse(markdown, {
status: 404,
headers: {
'Content-Type': 'text/markdown; charset=utf-8',
'Cache-Control': 'no-store',
},
})
}
+44
View File
@@ -0,0 +1,44 @@
export type PackageManager = 'npm' | 'pnpm' | 'yarn' | 'bun'
export type ShadcnFramework = 'react' | 'vue'
export function getShadcnFramework(name: string): ShadcnFramework {
return name.includes('vue') || name.includes('nuxtjs') ? 'vue' : 'react'
}
export function getRegistryBaseUrl(env = process.env.NEXT_PUBLIC_VERCEL_TARGET_ENV): string {
if (env === 'production') {
// Special alias for production, added in https://github.com/shadcn-ui/ui/pull/8161
return '@supabase'
}
if (env === 'preview') {
return `https://${process.env.NEXT_PUBLIC_VERCEL_BRANCH_URL}`
}
return 'http://localhost:3004'
}
export function getRegistryComponentPath(
name: string,
env = process.env.NEXT_PUBLIC_VERCEL_TARGET_ENV
): string {
if (env === 'production') {
return `/${name}`
}
return `${process.env.NEXT_PUBLIC_BASE_PATH ?? ''}/r/${name}.json`
}
export function getInstallCommands(
name: string,
options?: { framework?: ShadcnFramework; production?: boolean }
): Record<PackageManager, string> {
const framework = options?.framework ?? getShadcnFramework(name)
const env = options?.production ? 'production' : process.env.NEXT_PUBLIC_VERCEL_TARGET_ENV
const specifier = `${getRegistryBaseUrl(env)}${getRegistryComponentPath(name, env)}`
const cli = framework === 'vue' ? 'shadcn-vue@latest' : 'shadcn@latest'
return {
npm: `npx ${cli} add ${specifier}`,
pnpm: `pnpm dlx ${cli} add ${specifier}`,
yarn: `yarn dlx ${cli} add ${specifier}`,
bun: `bunx --bun ${cli} add ${specifier}`,
}
}
+50
View File
@@ -0,0 +1,50 @@
import assert from 'node:assert/strict'
import { describe, it } from 'node:test'
import { NextRequest } from 'next/server'
import { middleware } from './middleware'
const DOCS_URL = 'https://supabase.com/library/docs/nextjs/client'
function request(url: string, headers: Record<string, string>) {
return new NextRequest(new Request(url, { headers }))
}
describe('middleware markdown negotiation', () => {
it('rewrites to the markdown route when Accept prefers markdown', () => {
const response = middleware(request(DOCS_URL, { accept: 'text/markdown' }))
assert.equal(
response.headers.get('x-middleware-rewrite'),
'https://supabase.com/library/api/docs-md/nextjs/client'
)
})
it('406s when Accept rejects both html and markdown', () => {
const response = middleware(request(DOCS_URL, { accept: 'application/json' }))
assert.equal(response.status, 406)
})
it('passes Server Action requests through untouched', () => {
// Server Actions POST to the page URL with `Accept: text/x-component`.
const response = middleware(
request(DOCS_URL, {
accept: 'text/x-component',
'next-action': '7f1e0c0d5a1b2c3d4e5f60718293a4b5c6d7e8f900',
})
)
assert.equal(response.status, 200)
assert.equal(response.headers.get('x-middleware-rewrite'), null)
})
it('serves html to browsers', () => {
const response = middleware(
request(DOCS_URL, { accept: 'text/html,application/xhtml+xml,*/*;q=0.8' })
)
assert.equal(response.status, 200)
assert.equal(response.headers.get('x-middleware-rewrite'), null)
})
})
+50
View File
@@ -0,0 +1,50 @@
import { negotiateMarkdown } from 'common/markdown-negotiation'
import { NextResponse, type NextRequest } from 'next/server'
import MARKDOWN_SLUGS from '@/public/markdown/manifest.json'
const BASE_PATH = process.env.NEXT_PUBLIC_BASE_PATH ?? '/library'
const DOCS_PATH = `${BASE_PATH}/docs`
const MARKDOWN_SLUG_SET = new Set(MARKDOWN_SLUGS)
export function middleware(request: NextRequest) {
const url = new URL(request.url)
const { pathname } = url
if (!pathname.startsWith(`${DOCS_PATH}/`)) {
return NextResponse.next()
}
// Server Actions POST to the page URL with `Accept: text/x-component`, which
// matches none of the types this route negotiates and would 406. Let Next.js
// handle them.
if (request.headers.get('next-action')) {
return NextResponse.next()
}
const isMdSuffix = pathname.endsWith('.md')
const slug = pathname.replace(`${DOCS_PATH}/`, '').replace(/\.md$/, '')
const decision = negotiateMarkdown(
{ acceptHeader: request.headers.get('accept') ?? '' },
{ hasMarkdownVariant: MARKDOWN_SLUG_SET.has(slug), isMarkdownSuffix: isMdSuffix }
)
if (decision === 'not-acceptable') {
return new NextResponse('Not Acceptable', {
status: 406,
headers: { 'Cache-Control': 'no-store', Vary: 'Accept' },
})
}
if (decision === 'markdown') {
const rewriteUrl = new URL(url)
rewriteUrl.pathname = `${BASE_PATH}/api/docs-md/${slug}`
return NextResponse.rewrite(rewriteUrl)
}
return NextResponse.next()
}
export const config = {
matcher: ['/docs/:path*'],
}
+3
View File
@@ -12,6 +12,9 @@ const nextConfig = {
},
},
},
outputFileTracingIncludes: {
'/api/docs-md/**/*': ['./public/markdown/docs/**/*'],
},
async redirects() {
return [
...(process.env.NEXT_PUBLIC_BASE_PATH?.length
+14 -1
View File
@@ -6,9 +6,13 @@
"scripts": {
"preinstall": "npx only-allow pnpm",
"dev": "next dev --port 3004",
"build": "pnpm run content:build && pnpm run build:registry && pnpm run build:llms && pnpm run build:app",
"predev": "pnpm run build:markdown",
"build": "pnpm run content:build && pnpm run build:registry && pnpm run build:markdown && pnpm run build:llms && pnpm run build:app",
"build:registry": "rimraf -G public/r/* && tsx ./scripts/build-registry.mts && shadcn build public/r/registry.json && tsx scripts/clean-registry.ts",
"build:markdown": "tsx ./scripts/build-markdown.ts",
"build:llms": "tsx ./scripts/build-llms-txt.ts",
"test:markdown": "tsx --test scripts/library-mdx-to-markdown.test.ts",
"test:middleware": "pnpm run build:markdown && tsx --test middleware.test.ts",
"build:app": "next build --turbopack",
"start": "next start",
"lint": "eslint .",
@@ -78,12 +82,21 @@
"@tanstack/react-start": "catalog:",
"@types/common-tags": "^1.8.4",
"@types/lodash": "^4.17.16",
"@types/mdast": "^3.0.15",
"@types/react": "catalog:",
"@types/react-dom": "catalog:",
"@typescript/native": "catalog:",
"config": "workspace:^",
"gray-matter": "^4.0.3",
"lodash": "catalog:",
"mdast-util-from-markdown": "^1.3.1",
"mdast-util-gfm": "^2.0.2",
"mdast-util-mdx": "^2.0.1",
"mdast-util-mdx-jsx": "^2.1.4",
"mdast-util-to-markdown": "^1.5.0",
"mdast-util-toc": "^6.1.1",
"micromark-extension-gfm": "^2.0.3",
"micromark-extension-mdxjs": "^1.0.1",
"postcss": "catalog:",
"react-dropzone": "^14.3.8",
"react-router": "^7.13.2",
+2 -2
View File
@@ -81,14 +81,14 @@ let content = `# Supabase Library
Last updated: ${new Date().toISOString()}
## Overview
Library of components for your project. The components integrate with Supabase and are shadcn compatible.
Library of components for your project. The components integrate with Supabase and are shadcn compatible. Each docs page is also available as markdown for agents (append .md to the URL).
## Docs
`
// Add documentation links
for (const doc of docs) {
const url = `${BASE_URL}/${doc.path}`
const url = `${BASE_URL}/${doc.path}.md`
content += `- [${doc.title}](${url})`
if (doc.description) {
content += `\n - ${doc.description}`
+65
View File
@@ -0,0 +1,65 @@
import fs from 'node:fs/promises'
import path from 'node:path'
import { transformLibraryMdx } from './library-mdx-to-markdown'
const CONTENT_DIR = path.join(process.cwd(), 'content', 'docs')
const OUTPUT_DIR = path.join(process.cwd(), 'public', 'markdown', 'docs')
const MANIFEST_PATH = path.join(process.cwd(), 'public', 'markdown', 'manifest.json')
async function collectMdxFiles(dir: string): Promise<string[]> {
const entries = await fs.readdir(dir, { withFileTypes: true })
const files: string[] = []
for (const entry of entries) {
const fullPath = path.join(dir, entry.name)
if (entry.isDirectory()) {
files.push(...(await collectMdxFiles(fullPath)))
} else if (entry.name.endsWith('.mdx')) {
files.push(fullPath)
}
}
return files.sort((a, b) => a.localeCompare(b))
}
async function generate() {
const sources = await collectMdxFiles(CONTENT_DIR)
const slugs: string[] = []
// Wipe first so pages that were renamed or deleted don't leave stale markdown
// behind — public/markdown is served directly, and the files outlive the manifest.
await fs.rm(OUTPUT_DIR, { recursive: true, force: true })
await fs.mkdir(OUTPUT_DIR, { recursive: true })
for (const sourceFile of sources) {
const relativePath = path.relative(CONTENT_DIR, sourceFile)
const slug = relativePath.replace(/\.mdx$/, '').replace(/\\/g, '/')
const outPath = path.join(OUTPUT_DIR, `${slug}.md`)
const raw = await fs.readFile(sourceFile, 'utf8')
let output: string
try {
output = transformLibraryMdx(raw)
} catch (err) {
throw new Error(
`Failed to process ${sourceFile}: ${err instanceof Error ? err.message : err}`,
{ cause: err }
)
}
await fs.mkdir(path.dirname(outPath), { recursive: true })
await fs.writeFile(outPath, output)
slugs.push(slug)
}
await fs.mkdir(path.dirname(MANIFEST_PATH), { recursive: true })
await fs.writeFile(MANIFEST_PATH, `${JSON.stringify(slugs, null, 2)}\n`)
console.log(`Generated ${slugs.length} markdown files under public/markdown/docs/`)
}
generate().catch((error) => {
console.error(error)
process.exit(1)
})
@@ -0,0 +1,98 @@
import assert from 'node:assert/strict'
import { describe, it } from 'node:test'
import { transformLibraryMdx } from './library-mdx-to-markdown'
describe('transformLibraryMdx', () => {
it('lifts title and description into a markdown header', () => {
const output = transformLibraryMdx(`---
title: Password-based Authentication
description: Password-based authentication block for Next.js
---
Hello world.
`)
assert.match(
output,
/^# Password-based Authentication\n\nPassword-based authentication block for Next.js\n\nHello world.\n$/
)
})
it('replaces BlockItem with a production shadcn install command', () => {
const output = transformLibraryMdx(`---
title: Auth
description: Auth block
---
<BlockItem name="password-based-auth-nextjs" />
`)
assert.match(
output,
/```bash\nnpx shadcn@latest add @supabase\/password-based-auth-nextjs\n```/
)
})
it('uses shadcn-vue for Vue and Nuxt blocks', () => {
const output = transformLibraryMdx(`---
title: Dropzone
description: Vue dropzone
---
<BlockItem name="dropzone-vue" />
`)
assert.match(output, /npx shadcn-vue@latest add @supabase\/dropzone-vue/)
})
it('keeps usage copy and omits interactive previews', () => {
const output = transformLibraryMdx(`---
title: Auth
description: Auth block
---
<BlockPreview name="password-based-auth/auth/sign-up" />
## Usage
Set \`NEXT_PUBLIC_SUPABASE_URL\` in \`.env.local\`.
<Callout type="warning">This client is built for SSR.</Callout>
`)
assert.doesNotMatch(output, /BlockPreview/)
assert.match(output, /## Usage/)
assert.match(output, /NEXT_PUBLIC_SUPABASE_URL/)
assert.match(output, /Warning: This client is built for SSR\./)
})
it('rewrites library docs links to absolute markdown URLs', () => {
const output = transformLibraryMdx(`---
title: Client
description: Client
---
See the [React client](/library/docs/react/client).
`)
assert.match(output, /https:\/\/supabase\.com\/library\/docs\/react\/client\.md/)
})
it('rewrites documentation links nested inside components', () => {
const output = transformLibraryMdx(`---
title: Auth
description: Auth block
---
<Callout type="note">
See the [React client](/library/docs/react/client) before installing.
</Callout>
`)
assert.match(
output,
/Note: See the \[React client\]\(https:\/\/supabase\.com\/library\/docs\/react\/client\.md\) before installing\./
)
})
})
@@ -0,0 +1,109 @@
import matter from 'gray-matter'
import type { Content, Parent, Root } from 'mdast'
import { fromMarkdown } from 'mdast-util-from-markdown'
import { gfmFromMarkdown, gfmToMarkdown } from 'mdast-util-gfm'
import { mdxFromMarkdown, mdxToMarkdown } from 'mdast-util-mdx'
import type { MdxJsxFlowElement, MdxJsxTextElement } from 'mdast-util-mdx-jsx'
import { toMarkdown } from 'mdast-util-to-markdown'
import { gfm } from 'micromark-extension-gfm'
import { mdxjs } from 'micromark-extension-mdxjs'
import { visit } from 'unist-util-visit'
import { markdownSchema } from './markdown-schema'
type JsxNode = MdxJsxFlowElement | MdxJsxTextElement
type ComponentHandler = (ctx: {
props: Record<string, unknown>
children: string
node: JsxNode
}) => string
const PARSE_OPTIONS = {
extensions: [mdxjs(), gfm()],
mdastExtensions: [mdxFromMarkdown(), gfmFromMarkdown()],
}
const SERIALIZE_OPTIONS = {
extensions: [mdxToMarkdown(), gfmToMarkdown()],
bullet: '-' as const,
listItemIndent: 'one' as const,
}
const parseMdx = (source: string): Root => fromMarkdown(source, PARSE_OPTIONS)
const serializeMdx = (tree: Parent): string => toMarkdown(tree as Root, SERIALIZE_OPTIONS)
const defaultHandler: ComponentHandler = ({ children }) => children
const isJsx = (n: Content): n is JsxNode =>
n.type === 'mdxJsxFlowElement' || n.type === 'mdxJsxTextElement'
function propsFrom(node: JsxNode): Record<string, unknown> {
const props: Record<string, unknown> = {}
for (const attr of node.attributes) {
if (attr.type !== 'mdxJsxAttribute') continue
if (attr.value == null) props[attr.name] = true
else if (typeof attr.value === 'string') props[attr.name] = attr.value
else props[attr.name] = attr.value.value
}
return props
}
function applySchema(parent: Parent, schema: Record<string, ComponentHandler>): void {
for (const child of parent.children as Content[]) {
if ('children' in child) applySchema(child as Parent, schema)
}
const next: Content[] = []
for (const child of parent.children as Content[]) {
if (
child.type === 'mdxFlowExpression' ||
child.type === 'mdxTextExpression' ||
child.type === 'mdxjsEsm'
) {
continue
}
if (isJsx(child)) {
const handler = schema[child.name ?? ''] ?? defaultHandler
const children = serializeMdx({
type: 'root',
children: child.children as Root['children'],
}).trim()
const value = handler({ props: propsFrom(child), children, node: child })
if (value) {
next.push({ type: 'html', value } as Content)
}
continue
}
next.push(child)
}
parent.children = next as Parent['children']
}
function rewriteLibraryLinks(tree: Root): void {
visit(tree, 'link', (node) => {
if (!node.url.startsWith('/')) return
if (node.url.startsWith('//')) return
if (node.url.startsWith('/library/docs/')) {
const [pathname, hash] = node.url.split('#')
const withMd = pathname.endsWith('.md') ? pathname : `${pathname}.md`
node.url = `https://supabase.com${withMd}${hash ? `#${hash}` : ''}`
return
}
node.url = `https://supabase.com${node.url}`
})
}
export function transformLibraryMdx(raw: string): string {
const { content, data } = matter(raw)
const tree = parseMdx(content)
rewriteLibraryLinks(tree)
applySchema(tree, markdownSchema)
const body = serializeMdx(tree).trim()
const headerParts: string[] = []
if (data.title) headerParts.push(`# ${String(data.title)}`)
if (data.description) headerParts.push(String(data.description))
const header = headerParts.join('\n\n')
return `${header ? `${header}\n\n${body}` : body}\n`
}
+129
View File
@@ -0,0 +1,129 @@
import path from 'node:path'
import { getInstallCommands } from '../lib/install-command'
import { generateRegistryTree, type RegistryNode } from '../lib/process-registry'
type HandlerContext = {
props: Record<string, unknown>
children: string
}
type ComponentHandler = (ctx: HandlerContext) => string
const omit: ComponentHandler = () => ''
const unwrap: ComponentHandler = ({ children }) => children
function toAgentHref(href: string): string {
if (!href) return href
if (href.startsWith('/library/docs/')) {
const [pathname, hash] = href.split('#')
const withMd = pathname.endsWith('.md') ? pathname : `${pathname}.md`
return `https://supabase.com${withMd}${hash ? `#${hash}` : ''}`
}
if (href.startsWith('/') && !href.startsWith('//')) {
return `https://supabase.com${href}`
}
return href
}
function BlockItem({ props }: HandlerContext): string {
const name = String(props.name ?? '')
if (!name) return ''
const command = getInstallCommands(name, { production: true }).npm
return ['Install this block:', '', '```bash', command, '```'].join('\n')
}
function RegistryBlock({ props }: HandlerContext): string {
const itemName = String(props.itemName ?? '')
if (!itemName) return ''
const registryPath = path.join(process.cwd(), 'public', 'r', `${itemName}.json`)
let listing = ''
try {
const tree = generateRegistryTree(registryPath)
listing = formatTree(tree)
} catch {
listing = ''
}
const registryUrl = `https://supabase.com/library/r/${itemName}.json`
const parts = [listing, listing ? '' : null, `Full source: ${registryUrl}`].filter(
(part) => part !== null
)
return parts.join('\n').trim()
}
function formatTree(nodes: RegistryNode[], indent = 0): string {
return nodes
.map((node) => {
const prefix = `${' '.repeat(indent)}- \`${node.name}${node.type === 'directory' ? '/' : ''}\``
const children = node.children?.length ? `\n${formatTree(node.children, indent + 1)}` : ''
return `${prefix}${children}`
})
.join('\n')
}
function Callout({ props, children }: HandlerContext): string {
const type = String(props.type ?? 'note')
const label = type.charAt(0).toUpperCase() + type.slice(1)
return `${label}: ${children}`.trim()
}
function AccordionTrigger({ children }: HandlerContext): string {
const title = children.trim()
return title ? `**${title}**` : ''
}
function LinkedCard({ props, children }: HandlerContext): string {
const href = toAgentHref(String(props.href ?? ''))
const label = children.replace(/\s+/g, ' ').trim()
return href ? `- [${label || href}](${href})` : label
}
function ComponentPreview({ props }: HandlerContext): string {
const description = String(props.description ?? '').trim()
return description
}
function TanStackBeta(): string {
return 'Note: TanStack Start support is in beta. APIs may change.'
}
function TanstackDBGenerator(): string {
return [
'This block is generated from your project schema.',
'Open the HTML page to log in and generate an install command:',
'https://supabase.com/library/docs/nextjs/tanstack-db',
].join('\n')
}
function Anchor({ props, children }: HandlerContext): string {
const href = toAgentHref(String(props.href ?? ''))
return href ? `[${children}](${href})` : children
}
export const markdownSchema: Record<string, ComponentHandler> = {
BlockItem,
RegistryBlock,
Callout,
Accordion: unwrap,
AccordionItem: unwrap,
AccordionTrigger,
AccordionContent: unwrap,
Card: unwrap,
LinkedCard,
ComponentPreview,
BlockPreview: omit,
DualRealtimeChat: omit,
DualRealtimeFlow: omit,
DualRealtimeMonaco: omit,
RealtimeMonaco: omit,
TanStackBeta,
TanstackDBGenerator,
CopyButton: omit,
svg: omit,
path: omit,
title: omit,
a: Anchor,
}
+7 -1
View File
@@ -25,7 +25,13 @@
"SUPABASE_MANAGEMENT_API_TOKEN",
"OPENAI_API_KEY",
],
"outputs": [".next/**", "!.next/cache/**", "!.next/dev/**/*", ".contentlayer/**"],
"outputs": [
".next/**",
"!.next/cache/**",
"!.next/dev/**/*",
".contentlayer/**",
"public/markdown/**",
],
},
},
}
+6
View File
@@ -0,0 +1,6 @@
// public/markdown/manifest.json is generated by scripts/build-markdown.ts
// and gitignored, so it may not exist on disk when tsc runs.
declare module '@/public/markdown/manifest.json' {
const slugs: string[]
export = slugs
}
+85 -96
View File
@@ -596,7 +596,7 @@ importers:
version: 7.29.7(supports-color@8.1.1)
'@graphiql/toolkit':
specifier: ^0.9.1
version: 0.9.1(@types/node@22.13.14)(graphql-ws@6.0.4(graphql@16.11.0)(ws@8.21.0))(graphql@16.11.0)
version: 0.9.1(@types/node@22.13.14)(graphql-ws@6.0.4(graphql@16.11.0)(ws@8.21.3))(graphql@16.11.0)
'@graphql-codegen/cli':
specifier: 5.0.5
version: 5.0.5(@parcel/watcher@2.5.6)(@types/node@22.13.14)(encoding@0.1.13)(graphql-sock@1.0.1(graphql@16.11.0))(graphql@16.11.0)(supports-color@8.1.1)(typescript@6.0.2)
@@ -677,7 +677,7 @@ importers:
version: 13.2.2
graphiql:
specifier: ^4.0.2
version: 4.0.2(@codemirror/language@6.11.0)(@emotion/is-prop-valid@1.4.0)(@types/node@22.13.14)(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(graphql-ws@6.0.4(graphql@16.11.0)(ws@8.21.0))(graphql@16.11.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)
version: 4.0.2(@codemirror/language@6.11.0)(@emotion/is-prop-valid@1.4.0)(@types/node@22.13.14)(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(graphql-ws@6.0.4(graphql@16.11.0)(ws@8.21.3))(graphql@16.11.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)
npm-run-all:
specifier: ^4.1.5
version: 4.1.5
@@ -865,7 +865,7 @@ importers:
dependencies:
'@react-router/fs-routes':
specifier: ^7.17.0
version: 7.17.0(@react-router/dev@7.17.0(@react-router/serve@7.17.0(react-router@7.18.2(react-dom@19.2.6(react@19.2.6))(react@19.2.6))(supports-color@8.1.1)(typescript@6.0.2))(@types/node@22.13.14)(babel-plugin-macros@3.1.0)(jiti@2.7.0)(lightningcss@1.32.0)(react-router@7.18.2(react-dom@19.2.6(react@19.2.6))(react@19.2.6))(sass@1.77.4)(supports-color@8.1.1)(terser@5.39.0)(tsx@4.22.4)(typescript@6.0.2)(vite@7.3.5(@types/node@22.13.14)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.77.4)(terser@5.39.0)(tsx@4.22.4)(yaml@2.9.0))(yaml@2.9.0))(typescript@6.0.2)
version: 7.17.0(@react-router/dev@7.17.0(@react-router/serve@7.17.0(react-router@7.18.2(react-dom@19.2.6(react@19.2.6))(react@19.2.6))(supports-color@8.1.1)(typescript@6.0.2))(@types/node@22.13.14)(babel-plugin-macros@3.1.0)(jiti@2.7.0)(lightningcss@1.33.0)(react-router@7.18.2(react-dom@19.2.6(react@19.2.6))(react@19.2.6))(sass@1.77.4)(supports-color@8.1.1)(terser@5.39.0)(tsx@4.22.4)(typescript@6.0.2)(vite@7.3.5(@types/node@22.13.14)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.77.4)(terser@5.39.0)(tsx@4.22.4)(yaml@2.9.0))(yaml@2.9.0))(typescript@6.0.2)
'@react-router/node':
specifier: ^7.17.0
version: 7.17.0(react-router@7.18.2(react-dom@19.2.6(react@19.2.6))(react@19.2.6))(typescript@6.0.2)
@@ -893,7 +893,7 @@ importers:
devDependencies:
'@react-router/dev':
specifier: ^7.17.0
version: 7.17.0(@react-router/serve@7.17.0(react-router@7.18.2(react-dom@19.2.6(react@19.2.6))(react@19.2.6))(supports-color@8.1.1)(typescript@6.0.2))(@types/node@22.13.14)(babel-plugin-macros@3.1.0)(jiti@2.7.0)(lightningcss@1.32.0)(react-router@7.18.2(react-dom@19.2.6(react@19.2.6))(react@19.2.6))(sass@1.77.4)(supports-color@8.1.1)(terser@5.39.0)(tsx@4.22.4)(typescript@6.0.2)(vite@7.3.5(@types/node@22.13.14)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.77.4)(terser@5.39.0)(tsx@4.22.4)(yaml@2.9.0))(yaml@2.9.0)
version: 7.17.0(@react-router/serve@7.17.0(react-router@7.18.2(react-dom@19.2.6(react@19.2.6))(react@19.2.6))(supports-color@8.1.1)(typescript@6.0.2))(@types/node@22.13.14)(babel-plugin-macros@3.1.0)(jiti@2.7.0)(lightningcss@1.33.0)(react-router@7.18.2(react-dom@19.2.6(react@19.2.6))(react@19.2.6))(sass@1.77.4)(supports-color@8.1.1)(terser@5.39.0)(tsx@4.22.4)(typescript@6.0.2)(vite@7.3.5(@types/node@22.13.14)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.77.4)(terser@5.39.0)(tsx@4.22.4)(yaml@2.9.0))(yaml@2.9.0)
'@tailwindcss/vite':
specifier: 4.2.4
version: 4.2.4(vite@7.3.5(@types/node@22.13.14)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.77.4)(terser@5.39.0)(tsx@4.22.4)(yaml@2.9.0))
@@ -1634,6 +1634,9 @@ importers:
'@types/lodash':
specifier: ^4.17.16
version: 4.17.16
'@types/mdast':
specifier: ^3.0.15
version: 3.0.15
'@types/react':
specifier: 'catalog:'
version: 19.2.14
@@ -1646,12 +1649,36 @@ importers:
config:
specifier: workspace:^
version: link:../../packages/config
gray-matter:
specifier: ^4.0.3
version: 4.0.3
lodash:
specifier: ^4.18.1
version: 4.18.1
mdast-util-from-markdown:
specifier: ^1.3.1
version: 1.3.1(supports-color@8.1.1)
mdast-util-gfm:
specifier: ^2.0.2
version: 2.0.2(supports-color@8.1.1)
mdast-util-mdx:
specifier: ^2.0.1
version: 2.0.1(supports-color@8.1.1)
mdast-util-mdx-jsx:
specifier: ^2.1.4
version: 2.1.4(supports-color@8.1.1)
mdast-util-to-markdown:
specifier: ^1.5.0
version: 1.5.0
mdast-util-toc:
specifier: ^6.1.1
version: 6.1.1
micromark-extension-gfm:
specifier: ^2.0.3
version: 2.0.3
micromark-extension-mdxjs:
specifier: ^1.0.1
version: 1.0.1
postcss:
specifier: ^8.5.18
version: 8.5.22
@@ -9814,11 +9841,6 @@ packages:
engines: {node: '>=0.4.0'}
hasBin: true
acorn@8.14.1:
resolution: {integrity: sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==}
engines: {node: '>=0.4.0'}
hasBin: true
acorn@8.15.0:
resolution: {integrity: sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==}
engines: {node: '>=0.4.0'}
@@ -10730,6 +10752,7 @@ packages:
configcat-common@9.3.1:
resolution: {integrity: sha512-yVkIbluksD/kZfVyKjLIOpwLrq3/ZRM7Lwrsz89JmbpQ6VtbnelrTQynSPElTtKjrPRZx56v3IZYk3nWTnnM6A==}
deprecated: Official support for this package has ended. Please migrate to @configcat/sdk. For more information, see https://github.com/configcat/js-unified-sdk#getting-started
configcat-js@9.5.1:
resolution: {integrity: sha512-M7ZPMtS+wCJLsFwcMkXa/ka+r/uEbN5MYS1FEnnlM2cohvpR2vpvvSMe0fuhc83HDgXJari08LyRXay0k0S80g==}
@@ -12861,9 +12884,6 @@ packages:
htmlparser2@10.1.0:
resolution: {integrity: sha512-VTZkM9GWRAtEpveh7MSF6SjjrpNVNNVJfFup7xTY3UpFtm67foy9HDVXneLtFVt4pMz5kZtgNcvCniNFb1hlEQ==}
http-cache-semantics@4.1.1:
resolution: {integrity: sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==}
http-cache-semantics@4.2.0:
resolution: {integrity: sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==}
@@ -15331,9 +15351,6 @@ packages:
package-json-from-dist@1.0.1:
resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==}
package-manager-detector@1.3.0:
resolution: {integrity: sha512-ZsEbbZORsyHuO00lY1kV3/t72yp6Ysay6Pd17ZAlNGuGwmWDLCJxFpRs0IzfXfj1o4icJOkUEioexFHzyPurSQ==}
package-manager-detector@1.8.0:
resolution: {integrity: sha512-yQA4H19AmPEoMUeavPMDIe1higySl/gH/yaQrkT/s07Qp+7pp2hYz30N3z2l5BkjVkF9Ow6o0wjJamm2y7Sn0A==}
@@ -18971,14 +18988,14 @@ snapshots:
'@antfu/install-pkg@1.1.0':
dependencies:
package-manager-detector: 1.3.0
package-manager-detector: 1.8.0
tinyexec: 1.2.4
'@antfu/ni@25.0.0':
dependencies:
ansis: 4.1.0
fzf: 0.5.2
package-manager-detector: 1.3.0
package-manager-detector: 1.8.0
tinyexec: 1.2.4
'@antfu/utils@9.2.1': {}
@@ -19106,7 +19123,7 @@ snapshots:
'@astrojs/internal-helpers@0.10.4':
dependencies:
'@types/hast': 3.0.4
'@types/hast': 3.0.5
'@types/mdast': 4.0.4
js-yaml: 4.3.1
picomatch: 4.0.5
@@ -19277,17 +19294,17 @@ snapshots:
dependencies:
'@aws-sdk/types': 3.973.8
'@aws-sdk/xml-builder': 3.972.22
'@smithy/core': 3.23.17
'@smithy/core': 3.31.1
'@smithy/node-config-provider': 4.3.14
'@smithy/property-provider': 4.2.14
'@smithy/protocol-http': 5.3.14
'@smithy/signature-v4': 5.3.14
'@smithy/smithy-client': 4.12.13
'@smithy/types': 4.14.1
'@smithy/types': 4.16.1
'@smithy/util-base64': 4.3.2
'@smithy/util-middleware': 4.2.14
'@smithy/util-retry': 4.3.8
'@smithy/util-utf8': 4.2.2
'@smithy/util-utf8': 4.4.16
tslib: 2.8.1
'@aws-sdk/credential-provider-cognito-identity@3.972.31':
@@ -19553,7 +19570,7 @@ snapshots:
'@aws-sdk/types@3.973.8':
dependencies:
'@smithy/types': 4.14.1
'@smithy/types': 4.16.1
tslib: 2.8.1
'@aws-sdk/util-arn-parser@3.972.3':
@@ -19591,7 +19608,7 @@ snapshots:
'@aws-sdk/xml-builder@3.972.22':
dependencies:
'@nodable/entities': 2.1.0
'@smithy/types': 4.14.1
'@smithy/types': 4.16.1
fast-xml-parser: 5.7.2
tslib: 2.8.1
@@ -20665,9 +20682,9 @@ snapshots:
'@floating-ui/utils@0.2.9': {}
'@graphiql/plugin-doc-explorer@0.0.1(@codemirror/language@6.11.0)(@emotion/is-prop-valid@1.4.0)(@types/node@22.13.14)(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(graphql-ws@6.0.4(graphql@16.11.0)(ws@8.21.0))(graphql@16.11.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)':
'@graphiql/plugin-doc-explorer@0.0.1(@codemirror/language@6.11.0)(@emotion/is-prop-valid@1.4.0)(@types/node@22.13.14)(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(graphql-ws@6.0.4(graphql@16.11.0)(ws@8.21.3))(graphql@16.11.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)':
dependencies:
'@graphiql/react': 0.32.0(@codemirror/language@6.11.0)(@emotion/is-prop-valid@1.4.0)(@types/node@22.13.14)(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(graphql-ws@6.0.4(graphql@16.11.0)(ws@8.21.0))(graphql@16.11.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)
'@graphiql/react': 0.32.0(@codemirror/language@6.11.0)(@emotion/is-prop-valid@1.4.0)(@types/node@22.13.14)(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(graphql-ws@6.0.4(graphql@16.11.0)(ws@8.21.3))(graphql@16.11.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)
'@headlessui/react': 2.2.2(react-dom@19.2.6(react@19.2.6))(react@19.2.6)
graphql: 16.11.0
react: 19.2.6
@@ -20695,10 +20712,10 @@ snapshots:
- immer
- use-sync-external-store
'@graphiql/plugin-history@0.0.2(@codemirror/language@6.11.0)(@emotion/is-prop-valid@1.4.0)(@types/node@22.13.14)(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(graphql-ws@6.0.4(graphql@16.11.0)(ws@8.21.0))(graphql@16.11.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)':
'@graphiql/plugin-history@0.0.2(@codemirror/language@6.11.0)(@emotion/is-prop-valid@1.4.0)(@types/node@22.13.14)(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(graphql-ws@6.0.4(graphql@16.11.0)(ws@8.21.3))(graphql@16.11.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)':
dependencies:
'@graphiql/react': 0.32.0(@codemirror/language@6.11.0)(@emotion/is-prop-valid@1.4.0)(@types/node@22.13.14)(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(graphql-ws@6.0.4(graphql@16.11.0)(ws@8.21.0))(graphql@16.11.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)
'@graphiql/toolkit': 0.11.3(@types/node@22.13.14)(graphql-ws@6.0.4(graphql@16.11.0)(ws@8.21.0))(graphql@16.11.0)
'@graphiql/react': 0.32.0(@codemirror/language@6.11.0)(@emotion/is-prop-valid@1.4.0)(@types/node@22.13.14)(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(graphql-ws@6.0.4(graphql@16.11.0)(ws@8.21.3))(graphql@16.11.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)
'@graphiql/toolkit': 0.11.3(@types/node@22.13.14)(graphql-ws@6.0.4(graphql@16.11.0)(ws@8.21.3))(graphql@16.11.0)
react: 19.2.6
react-compiler-runtime: 19.1.0-rc.1(react@19.2.6)
react-dom: 19.2.6(react@19.2.6)
@@ -20727,9 +20744,9 @@ snapshots:
- immer
- use-sync-external-store
'@graphiql/react@0.32.0(@codemirror/language@6.11.0)(@emotion/is-prop-valid@1.4.0)(@types/node@22.13.14)(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(graphql-ws@6.0.4(graphql@16.11.0)(ws@8.21.0))(graphql@16.11.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)':
'@graphiql/react@0.32.0(@codemirror/language@6.11.0)(@emotion/is-prop-valid@1.4.0)(@types/node@22.13.14)(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(graphql-ws@6.0.4(graphql@16.11.0)(ws@8.21.3))(graphql@16.11.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)':
dependencies:
'@graphiql/toolkit': 0.11.3(@types/node@22.13.14)(graphql-ws@6.0.4(graphql@16.11.0)(ws@8.21.0))(graphql@16.11.0)
'@graphiql/toolkit': 0.11.3(@types/node@22.13.14)(graphql-ws@6.0.4(graphql@16.11.0)(ws@8.21.3))(graphql@16.11.0)
'@radix-ui/react-dialog': 1.1.15(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)
'@radix-ui/react-dropdown-menu': 2.1.16(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)
'@radix-ui/react-tooltip': 1.2.8(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)
@@ -20797,23 +20814,23 @@ snapshots:
transitivePeerDependencies:
- '@types/node'
'@graphiql/toolkit@0.11.3(@types/node@22.13.14)(graphql-ws@6.0.4(graphql@16.11.0)(ws@8.21.0))(graphql@16.11.0)':
'@graphiql/toolkit@0.11.3(@types/node@22.13.14)(graphql-ws@6.0.4(graphql@16.11.0)(ws@8.21.3))(graphql@16.11.0)':
dependencies:
'@n1ru4l/push-pull-async-iterable-iterator': 3.2.0
graphql: 16.11.0
meros: 1.3.0(@types/node@22.13.14)
optionalDependencies:
graphql-ws: 6.0.4(graphql@16.11.0)(ws@8.21.0)
graphql-ws: 6.0.4(graphql@16.11.0)(ws@8.21.3)
transitivePeerDependencies:
- '@types/node'
'@graphiql/toolkit@0.9.1(@types/node@22.13.14)(graphql-ws@6.0.4(graphql@16.11.0)(ws@8.21.0))(graphql@16.11.0)':
'@graphiql/toolkit@0.9.1(@types/node@22.13.14)(graphql-ws@6.0.4(graphql@16.11.0)(ws@8.21.3))(graphql@16.11.0)':
dependencies:
'@n1ru4l/push-pull-async-iterable-iterator': 3.2.0
graphql: 16.11.0
meros: 1.3.0(@types/node@22.13.14)
optionalDependencies:
graphql-ws: 6.0.4(graphql@16.11.0)(ws@8.21.0)
graphql-ws: 6.0.4(graphql@16.11.0)(ws@8.21.3)
transitivePeerDependencies:
- '@types/node'
@@ -23916,7 +23933,7 @@ snapshots:
- tsx
- yaml
'@react-router/dev@7.17.0(@react-router/serve@7.17.0(react-router@7.18.2(react-dom@19.2.6(react@19.2.6))(react@19.2.6))(supports-color@8.1.1)(typescript@6.0.2))(@types/node@22.13.14)(babel-plugin-macros@3.1.0)(jiti@2.7.0)(lightningcss@1.32.0)(react-router@7.18.2(react-dom@19.2.6(react@19.2.6))(react@19.2.6))(sass@1.77.4)(supports-color@8.1.1)(terser@5.39.0)(tsx@4.22.4)(typescript@6.0.2)(vite@7.3.5(@types/node@22.13.14)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.77.4)(terser@5.39.0)(tsx@4.22.4)(yaml@2.9.0))(yaml@2.9.0)':
'@react-router/dev@7.17.0(@react-router/serve@7.17.0(react-router@7.18.2(react-dom@19.2.6(react@19.2.6))(react@19.2.6))(supports-color@8.1.1)(typescript@6.0.2))(@types/node@22.13.14)(babel-plugin-macros@3.1.0)(jiti@2.7.0)(lightningcss@1.33.0)(react-router@7.18.2(react-dom@19.2.6(react@19.2.6))(react@19.2.6))(sass@1.77.4)(supports-color@8.1.1)(terser@5.39.0)(tsx@4.22.4)(typescript@6.0.2)(vite@7.3.5(@types/node@22.13.14)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.77.4)(terser@5.39.0)(tsx@4.22.4)(yaml@2.9.0))(yaml@2.9.0)':
dependencies:
'@babel/core': 7.29.7(supports-color@8.1.1)
'@babel/generator': 7.29.0
@@ -23947,7 +23964,7 @@ snapshots:
tinyglobby: 0.2.16
valibot: 1.4.2(typescript@6.0.2)
vite: 7.3.5(@types/node@22.13.14)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.77.4)(terser@5.39.0)(tsx@4.22.4)(yaml@2.9.0)
vite-node: 3.2.4(@types/node@22.13.14)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.77.4)(supports-color@8.1.1)(terser@5.39.0)(tsx@4.22.4)(yaml@2.9.0)
vite-node: 3.2.4(@types/node@22.13.14)(jiti@2.7.0)(lightningcss@1.33.0)(sass@1.77.4)(supports-color@8.1.1)(terser@5.39.0)(tsx@4.22.4)(yaml@2.9.0)
optionalDependencies:
'@react-router/serve': 7.17.0(react-router@7.18.2(react-dom@19.2.6(react@19.2.6))(react@19.2.6))(supports-color@8.1.1)(typescript@6.0.2)
typescript: 6.0.2
@@ -23974,9 +23991,9 @@ snapshots:
optionalDependencies:
typescript: 6.0.2
'@react-router/fs-routes@7.17.0(@react-router/dev@7.17.0(@react-router/serve@7.17.0(react-router@7.18.2(react-dom@19.2.6(react@19.2.6))(react@19.2.6))(supports-color@8.1.1)(typescript@6.0.2))(@types/node@22.13.14)(babel-plugin-macros@3.1.0)(jiti@2.7.0)(lightningcss@1.32.0)(react-router@7.18.2(react-dom@19.2.6(react@19.2.6))(react@19.2.6))(sass@1.77.4)(supports-color@8.1.1)(terser@5.39.0)(tsx@4.22.4)(typescript@6.0.2)(vite@7.3.5(@types/node@22.13.14)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.77.4)(terser@5.39.0)(tsx@4.22.4)(yaml@2.9.0))(yaml@2.9.0))(typescript@6.0.2)':
'@react-router/fs-routes@7.17.0(@react-router/dev@7.17.0(@react-router/serve@7.17.0(react-router@7.18.2(react-dom@19.2.6(react@19.2.6))(react@19.2.6))(supports-color@8.1.1)(typescript@6.0.2))(@types/node@22.13.14)(babel-plugin-macros@3.1.0)(jiti@2.7.0)(lightningcss@1.33.0)(react-router@7.18.2(react-dom@19.2.6(react@19.2.6))(react@19.2.6))(sass@1.77.4)(supports-color@8.1.1)(terser@5.39.0)(tsx@4.22.4)(typescript@6.0.2)(vite@7.3.5(@types/node@22.13.14)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.77.4)(terser@5.39.0)(tsx@4.22.4)(yaml@2.9.0))(yaml@2.9.0))(typescript@6.0.2)':
dependencies:
'@react-router/dev': 7.17.0(@react-router/serve@7.17.0(react-router@7.18.2(react-dom@19.2.6(react@19.2.6))(react@19.2.6))(supports-color@8.1.1)(typescript@6.0.2))(@types/node@22.13.14)(babel-plugin-macros@3.1.0)(jiti@2.7.0)(lightningcss@1.32.0)(react-router@7.18.2(react-dom@19.2.6(react@19.2.6))(react@19.2.6))(sass@1.77.4)(supports-color@8.1.1)(terser@5.39.0)(tsx@4.22.4)(typescript@6.0.2)(vite@7.3.5(@types/node@22.13.14)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.77.4)(terser@5.39.0)(tsx@4.22.4)(yaml@2.9.0))(yaml@2.9.0)
'@react-router/dev': 7.17.0(@react-router/serve@7.17.0(react-router@7.18.2(react-dom@19.2.6(react@19.2.6))(react@19.2.6))(supports-color@8.1.1)(typescript@6.0.2))(@types/node@22.13.14)(babel-plugin-macros@3.1.0)(jiti@2.7.0)(lightningcss@1.33.0)(react-router@7.18.2(react-dom@19.2.6(react@19.2.6))(react@19.2.6))(sass@1.77.4)(supports-color@8.1.1)(terser@5.39.0)(tsx@4.22.4)(typescript@6.0.2)(vite@7.3.5(@types/node@22.13.14)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.77.4)(terser@5.39.0)(tsx@4.22.4)(yaml@2.9.0))(yaml@2.9.0)
minimatch: 9.0.7
optionalDependencies:
typescript: 6.0.2
@@ -24923,11 +24940,11 @@ snapshots:
dependencies:
'@smithy/is-array-buffer': 4.2.2
'@smithy/protocol-http': 5.3.14
'@smithy/types': 4.14.1
'@smithy/types': 4.16.1
'@smithy/util-hex-encoding': 4.2.2
'@smithy/util-middleware': 4.2.14
'@smithy/util-uri-escape': 4.2.2
'@smithy/util-utf8': 4.2.2
'@smithy/util-utf8': 4.4.16
tslib: 2.8.1
'@smithy/smithy-client@4.12.13':
@@ -27098,10 +27115,6 @@ snapshots:
dependencies:
acorn: 8.15.0
acorn-import-attributes@1.9.5(acorn@8.16.0):
dependencies:
acorn: 8.16.0
acorn-import-attributes@1.9.5(acorn@8.18.0):
dependencies:
acorn: 8.18.0
@@ -27110,10 +27123,6 @@ snapshots:
dependencies:
acorn: 8.18.0
acorn-jsx@5.3.2(acorn@8.14.1):
dependencies:
acorn: 8.14.1
acorn-jsx@5.3.2(acorn@8.16.0):
dependencies:
acorn: 8.16.0
@@ -27128,12 +27137,10 @@ snapshots:
acorn-walk@8.3.4:
dependencies:
acorn: 8.16.0
acorn: 8.18.0
acorn@8.11.3: {}
acorn@8.14.1: {}
acorn@8.15.0: {}
acorn@8.16.0: {}
@@ -29163,7 +29170,7 @@ snapshots:
esast-util-from-estree@2.0.0:
dependencies:
'@types/estree-jsx': 1.0.1
'@types/estree-jsx': 1.0.5
devlop: 1.1.0
estree-util-visit: 2.0.0
unist-util-position-from-estree: 2.0.0
@@ -29568,7 +29575,7 @@ snapshots:
estree-util-visit@2.0.0:
dependencies:
'@types/estree-jsx': 1.0.1
'@types/estree-jsx': 1.0.5
'@types/unist': 3.0.3
estree-walker@2.0.2: {}
@@ -30296,11 +30303,11 @@ snapshots:
graceful-fs@4.2.11: {}
graphiql@4.0.2(@codemirror/language@6.11.0)(@emotion/is-prop-valid@1.4.0)(@types/node@22.13.14)(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(graphql-ws@6.0.4(graphql@16.11.0)(ws@8.21.0))(graphql@16.11.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6):
graphiql@4.0.2(@codemirror/language@6.11.0)(@emotion/is-prop-valid@1.4.0)(@types/node@22.13.14)(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(graphql-ws@6.0.4(graphql@16.11.0)(ws@8.21.3))(graphql@16.11.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6):
dependencies:
'@graphiql/plugin-doc-explorer': 0.0.1(@codemirror/language@6.11.0)(@emotion/is-prop-valid@1.4.0)(@types/node@22.13.14)(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(graphql-ws@6.0.4(graphql@16.11.0)(ws@8.21.0))(graphql@16.11.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)
'@graphiql/plugin-history': 0.0.2(@codemirror/language@6.11.0)(@emotion/is-prop-valid@1.4.0)(@types/node@22.13.14)(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(graphql-ws@6.0.4(graphql@16.11.0)(ws@8.21.0))(graphql@16.11.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)
'@graphiql/react': 0.32.0(@codemirror/language@6.11.0)(@emotion/is-prop-valid@1.4.0)(@types/node@22.13.14)(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(graphql-ws@6.0.4(graphql@16.11.0)(ws@8.21.0))(graphql@16.11.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)
'@graphiql/plugin-doc-explorer': 0.0.1(@codemirror/language@6.11.0)(@emotion/is-prop-valid@1.4.0)(@types/node@22.13.14)(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(graphql-ws@6.0.4(graphql@16.11.0)(ws@8.21.3))(graphql@16.11.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)
'@graphiql/plugin-history': 0.0.2(@codemirror/language@6.11.0)(@emotion/is-prop-valid@1.4.0)(@types/node@22.13.14)(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(graphql-ws@6.0.4(graphql@16.11.0)(ws@8.21.3))(graphql@16.11.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)
'@graphiql/react': 0.32.0(@codemirror/language@6.11.0)(@emotion/is-prop-valid@1.4.0)(@types/node@22.13.14)(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(graphql-ws@6.0.4(graphql@16.11.0)(ws@8.21.3))(graphql@16.11.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)
graphql: 16.11.0
react: 19.2.6
react-compiler-runtime: 19.1.0-rc.1(react@19.2.6)
@@ -30399,6 +30406,13 @@ snapshots:
optionalDependencies:
ws: 8.21.0
graphql-ws@6.0.4(graphql@16.11.0)(ws@8.21.3):
dependencies:
graphql: 16.11.0
optionalDependencies:
ws: 8.21.3
optional: true
graphql@16.11.0: {}
gray-matter@2.1.1:
@@ -30521,7 +30535,7 @@ snapshots:
hast-util-from-parse5@8.0.1:
dependencies:
'@types/hast': 3.0.4
'@types/hast': 3.0.5
'@types/unist': 3.0.3
devlop: 1.1.0
hastscript: 8.0.0
@@ -30548,7 +30562,7 @@ snapshots:
hast-util-parse-selector@4.0.0:
dependencies:
'@types/hast': 3.0.4
'@types/hast': 3.0.5
hast-util-raw@9.0.1:
dependencies:
@@ -30623,7 +30637,7 @@ snapshots:
hast-util-to-parse5@8.0.0:
dependencies:
'@types/hast': 3.0.4
'@types/hast': 3.0.5
comma-separated-tokens: 2.0.3
devlop: 1.1.0
property-information: 6.3.0
@@ -30660,7 +30674,7 @@ snapshots:
hastscript@8.0.0:
dependencies:
'@types/hast': 3.0.4
'@types/hast': 3.0.5
comma-separated-tokens: 2.0.3
hast-util-parse-selector: 4.0.0
property-information: 6.3.0
@@ -30718,8 +30732,6 @@ snapshots:
domutils: 3.2.2
entities: 7.0.1
http-cache-semantics@4.1.1: {}
http-cache-semantics@4.2.0: {}
http-errors@2.0.0:
@@ -30842,8 +30854,8 @@ snapshots:
import-in-the-middle@3.1.0:
dependencies:
acorn: 8.16.0
acorn-import-attributes: 1.9.5(acorn@8.16.0)
acorn: 8.18.0
acorn-import-attributes: 1.9.5(acorn@8.18.0)
cjs-module-lexer: 2.2.0
module-details-from-path: 1.0.4
@@ -31851,7 +31863,7 @@ snapshots:
dependencies:
'@npmcli/agent': 2.2.2(supports-color@8.1.1)
cacache: 18.0.3
http-cache-semantics: 4.1.1
http-cache-semantics: 4.2.0
is-lambda: 1.0.1
minipass: 7.1.3
minipass-fetch: 3.0.5
@@ -32591,8 +32603,8 @@ snapshots:
micromark-extension-mdxjs@1.0.1:
dependencies:
acorn: 8.14.1
acorn-jsx: 5.3.2(acorn@8.14.1)
acorn: 8.18.0
acorn-jsx: 5.3.2(acorn@8.18.0)
micromark-extension-mdx-expression: 1.0.8
micromark-extension-mdx-jsx: 1.0.5
micromark-extension-mdx-md: 1.0.1
@@ -32602,8 +32614,8 @@ snapshots:
micromark-extension-mdxjs@3.0.0:
dependencies:
acorn: 8.16.0
acorn-jsx: 5.3.2(acorn@8.16.0)
acorn: 8.18.0
acorn-jsx: 5.3.2(acorn@8.18.0)
micromark-extension-mdx-expression: 3.0.0
micromark-extension-mdx-jsx: 3.0.1
micromark-extension-mdx-md: 2.0.0
@@ -33990,8 +34002,6 @@ snapshots:
package-json-from-dist@1.0.1: {}
package-manager-detector@1.3.0: {}
package-manager-detector@1.8.0: {}
pako@0.2.9: {}
@@ -35977,7 +35987,7 @@ snapshots:
sirv@2.0.4:
dependencies:
'@polka/url': 1.0.0-next.25
mrmime: 2.0.0
mrmime: 2.0.1
totalist: 3.0.1
sirv@3.0.2:
@@ -37048,7 +37058,7 @@ snapshots:
unplugin@2.3.11:
dependencies:
'@jridgewell/remapping': 2.3.5
acorn: 8.16.0
acorn: 8.18.0
picomatch: 4.0.5
webpack-virtual-modules: 0.6.2
@@ -37314,27 +37324,6 @@ snapshots:
dependencies:
vite: 7.3.5(@types/node@22.13.14)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.77.4)(terser@5.39.0)(tsx@4.22.4)(yaml@2.9.0)
vite-node@3.2.4(@types/node@22.13.14)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.77.4)(supports-color@8.1.1)(terser@5.39.0)(tsx@4.22.4)(yaml@2.9.0):
dependencies:
cac: 6.7.14
debug: 4.4.3(supports-color@8.1.1)
es-module-lexer: 1.7.0
pathe: 2.0.3
vite: 7.3.5(@types/node@22.13.14)(jiti@2.7.0)(lightningcss@1.32.0)(sass@1.77.4)(terser@5.39.0)(tsx@4.22.4)(yaml@2.9.0)
transitivePeerDependencies:
- '@types/node'
- jiti
- less
- lightningcss
- sass
- sass-embedded
- stylus
- sugarss
- supports-color
- terser
- tsx
- yaml
vite-node@3.2.4(@types/node@22.13.14)(jiti@2.7.0)(lightningcss@1.33.0)(sass@1.77.4)(supports-color@8.1.1)(terser@5.39.0)(tsx@4.22.4)(yaml@2.9.0):
dependencies:
cac: 6.7.14
@@ -37691,7 +37680,7 @@ snapshots:
webpack-bundle-analyzer@4.10.1:
dependencies:
'@discoveryjs/json-ext': 0.5.7
acorn: 8.16.0
acorn: 8.18.0
acorn-walk: 8.3.4
commander: 7.2.0
debounce: 1.2.1