Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions packages/docs/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,6 @@ yarn-error.log*
next-env.d.ts
# Sentry Config File
.sentryclirc

# shadcn registry output
public/r
2 changes: 1 addition & 1 deletion packages/docs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
"dev": "next dev --turbo",
"build": "pnpm run build:registry && pnpm run build:next",
"build:next": "next build",
"build:registry": "shadcn build --output ./public",
"build:registry": "shadcn build",
"start": "next start",
"postinstall": "fumadocs-mdx",
"test": "tsc"
Expand Down
19 changes: 0 additions & 19 deletions packages/docs/public/next-typed-links.json

This file was deleted.

21 changes: 0 additions & 21 deletions packages/docs/public/registry.json

This file was deleted.

10 changes: 4 additions & 6 deletions packages/docs/src/app/(pages)/blog/page.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { blog } from '@/src/app/source'
import { Description } from '@/src/components/typography'
import {
Breadcrumb,
BreadcrumbItem,
Expand All @@ -9,6 +8,7 @@ import {
BreadcrumbSeparator
} from '@/src/components/ui/breadcrumb'
import { Card } from 'fumadocs-ui/components/card'
import { DocsDescription, DocsTitle } from 'fumadocs-ui/page'
import { RssIcon } from 'lucide-react'
import Link from 'next/link'
import { ComponentProps } from 'react'
Expand Down Expand Up @@ -36,12 +36,10 @@ export default async function BlogIndexPage() {
</Breadcrumb>
<div className="container max-w-[900px] py-12 md:px-8">
<nav className="mb-4 flex items-center justify-between">
<h1 className="text-4xl font-bold text-foreground sm:text-5xl">
Blog
</h1>
<DocsTitle>Blog</DocsTitle>
<RssFeedLink />
</nav>
<Description>URL state management with nuqs</Description>
<DocsDescription>URL state management with nuqs</DocsDescription>
</div>
<ul className="container max-w-[900px] space-y-4 pb-24 lg:px-4">
{posts.map(post => (
Expand Down Expand Up @@ -93,7 +91,7 @@ function RssFeedLink() {
return (
<a
href="/blog/rss.xml"
className="flex items-center gap-1 text-sm text-muted-foreground hover:underline"
className="text-muted-foreground flex items-center gap-1 text-sm hover:underline"
>
<RssIcon
className="size-4 text-orange-600 dark:text-orange-400"
Expand Down
29 changes: 1 addition & 28 deletions packages/docs/src/app/docs/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { source } from '@/src/app/source'
import { getSharedLayoutProps } from '@/src/components/shared-layout'
import { SidebarFooter } from '@/src/components/sidebar-footer'
import { DocsLayout } from 'fumadocs-ui/layouts/notebook'
import { Suspense, type ReactNode } from 'react'

Expand All @@ -25,31 +26,3 @@ export default function RootDocsLayout({ children }: { children: ReactNode }) {
</DocsLayout>
)
}

async function SidebarFooter() {
const version = await getLatestVersion()
return (
<footer className="flex w-full items-baseline gap-2 text-zinc-600 dark:text-zinc-400">
<a
href={`https://npmjs.com/package/nuqs/v/${version}`}
className="hover:underline"
tabIndex={-1}
>
<pre className="text-xs">nuqs@{version}</pre>
</a>
</footer>
)
}

async function getLatestVersion() {
try {
const res = await fetch('https://registry.npmjs.org/nuqs', {
next: {
tags: ['npm']
}
}).then(r => r.json())
return res['dist-tags'].latest
} catch {
return 'latest'
}
}
6 changes: 2 additions & 4 deletions packages/docs/src/app/playground/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { getSharedLayoutProps } from '@/src/components/shared-layout'
import { DocsLayout } from 'fumadocs-ui/layouts/notebook'
import { DocsBody, DocsPage } from 'fumadocs-ui/page'
import React, { Suspense } from 'react'
import { getPlaygroundTree } from './(demos)/demos'
import { DebugControl } from './debug-control'
Expand All @@ -26,6 +25,7 @@ export default function PlaygroundLayout({
{...shared}
nav={{ ...shared.nav, mode: 'top' }}
sidebar={{
collapsible: false,
// banner: // note: side banner goes here
footer: (
<Suspense fallback={<DebugControlsSkeleton />}>
Expand All @@ -34,9 +34,7 @@ export default function PlaygroundLayout({
)
}}
>
<DocsPage>
<DocsBody>{children}</DocsBody>
</DocsPage>
{children}
</DocsLayout>
</>
)
Expand Down
39 changes: 23 additions & 16 deletions packages/docs/src/app/playground/page.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
import { Description, H1 } from '@/src/components/typography'
import { Card } from 'fumadocs-ui/components/card'
import {
DocsBody,
DocsDescription,
DocsPage,
DocsTitle
} from 'fumadocs-ui/page'
import { demos } from './(demos)/demos'

export const metadata = {
Expand All @@ -9,20 +14,22 @@ export const metadata = {

export default function PlaygroundIndexPage() {
return (
<main className="py-6 md:py-10">
<H1>{metadata.title}</H1>
<Description>{metadata.description}</Description>
<ul className="not-prose my-8 space-y-2">
{Object.entries(demos).map(([path, { title, description }]) => (
<li key={path}>
<Card
title={title}
description={description}
href={`/playground/${path}`}
/>
</li>
))}
</ul>
</main>
<DocsPage>
<DocsTitle>{metadata.title}</DocsTitle>
<DocsDescription>{metadata.description}</DocsDescription>
<DocsBody>
<ul className="not-prose my-8 space-y-2">
{Object.entries(demos).map(([path, { title, description }]) => (
<li key={path}>
<Card
title={title}
description={description}
href={`/playground/${path}`}
/>
</li>
))}
</ul>
</DocsBody>
</DocsPage>
)
}
27 changes: 27 additions & 0 deletions packages/docs/src/app/registry/_lib/read.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { readFile } from 'node:fs/promises'
import { resolve } from 'node:path'
import { registryItemSchema, registrySchema } from './schemas'

export async function readRegistry() {
const fileName = resolve(process.cwd(), 'public/r/registry.json')
const fileContents = await readFile(fileName, 'utf-8')
return registrySchema.parse(JSON.parse(fileContents))
}

export async function readRegistryItem(name: string) {
const fileName = resolve(process.cwd(), `public/r/${name}.json`)
const fileContents = await readFile(fileName, 'utf-8')
return registryItemSchema.parse(JSON.parse(fileContents))
}

export async function readUsage(name: string) {
try {
const fileName = resolve(
process.cwd(),
`src/app/registry/_usage/${name}.md`
)
return await readFile(fileName, 'utf-8')
} catch {
return null
}
}
36 changes: 36 additions & 0 deletions packages/docs/src/app/registry/_lib/schemas.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { z } from 'zod'

const registrySourceFileSchema = z.object({
type: z.literal('registry:file'),
path: z.string(),
target: z.string()
})
export type RegistryFile = z.infer<typeof registryBuiltFileSchema>
const registryBuiltFileSchema = registrySourceFileSchema.extend({
content: z.string()
})

const registryBaseItemSchema = z.object({
type: z.literal('registry:item'),
name: z.string(),
title: z.string(),
description: z.string().optional(),
dependencies: z.array(z.string())
})

// Shape of individually built registry-item.json files
export type RegistryItem = z.infer<typeof registryItemSchema>
export const registryItemSchema = registryBaseItemSchema.extend({
files: z.array(registryBuiltFileSchema)
})

// Shape of the root registry.json file
export const registrySchema = z.object({
name: z.string(),
homepage: z.url(),
items: z.array(
registryBaseItemSchema.extend({
files: z.array(registrySourceFileSchema)
})
)
})
30 changes: 30 additions & 0 deletions packages/docs/src/app/registry/_usage/next-typed-links.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
This utility connects your `typedRoutes` type-safe pathnames
to a search params descriptor object, and gives you back a function
you can call to generate a fully type-safe (pathname + search params) href
for linking & routing:

```ts title="src/app/map/search-params.ts"
import { createTypedLink } from '@/src/lib/typed-links'
import { parseAsFloat, type UrlKeys } from 'nuqs/server'

const coordinates = {
latitude: parseAsFloat.withDefault(0),
longitude: parseAsFloat.withDefault(0)
}
// Optional remapping for shorter keys
const urlKeys: UrlKeys<typeof coordinates> = {
latitude: 'lat',
longitude: 'lng'
}

// [!code word:createTypedLink]
export const getMapLink = createTypedLink(
'/map', // The values here are inferred from your app's routes
coordinates,
{ urlKeys }
)

// Usage:
getMapLink({ latitude: 12.34, longitude: 56.78 })
// "/map?lat=12.34&lng=56.78"
```
35 changes: 35 additions & 0 deletions packages/docs/src/app/registry/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { getSharedLayoutProps } from '@/src/components/shared-layout'
import { SidebarFooter } from '@/src/components/sidebar-footer'
import { DocsLayout } from 'fumadocs-ui/layouts/notebook'
import { Suspense, type ReactNode } from 'react'

export default async function RegistryLayout({
children
}: {
children: ReactNode
}) {
const shared = getSharedLayoutProps()
return (
<>
<DocsLayout
tree={{
name: 'Registry',
children: []
}}
{...shared}
nav={{ ...shared.nav, mode: 'top' }}
sidebar={{
collapsible: false,
// banner: // note: side banner goes here
footer: (
<Suspense>
<SidebarFooter />
</Suspense>
)
}}
>
{children}
</DocsLayout>
</>
)
}
Loading