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
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,8 @@ coverage/
# generated native folders
/ios
/android

# fumadocs
apps/docs/.next/
apps/docs/.source/
apps/docs/node_modules/
26 changes: 26 additions & 0 deletions apps/docs/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# deps
/node_modules

# generated content
.source

# test & build
/coverage
/.next/
/out/
/build
*.tsbuildinfo

# misc
.DS_Store
*.pem
/.pnp
.pnp.js
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# others
.env*.local
.vercel
next-env.d.ts
45 changes: 45 additions & 0 deletions apps/docs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# docs

This is a Next.js application generated with
[Create Fumadocs](https://github.com/fuma-nama/fumadocs).

Run development server:

```bash
npm run dev
# or
pnpm dev
# or
yarn dev
```

Open http://localhost:3000 with your browser to see the result.

## Explore

In the project, you can see:

- `lib/source.ts`: Code for content source adapter, [`loader()`](https://fumadocs.dev/docs/headless/source-api) provides the interface to access your content.
- `lib/layout.shared.tsx`: Shared options for layouts, optional but preferred to keep.

| Route | Description |
| ------------------------- | ------------------------------------------------------ |
| `app/(home)` | The route group for your landing page and other pages. |
| `app/docs` | The documentation layout and pages. |
| `app/api/search/route.ts` | The Route Handler for search. |

### Fumadocs MDX

A `source.config.ts` config file has been included, you can customise different options like frontmatter schema.

Read the [Introduction](https://fumadocs.dev/docs/mdx) for further details.

## Learn More

To learn more about Next.js and Fumadocs, take a look at the following
resources:

- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js
features and API.
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
- [Fumadocs](https://fumadocs.dev) - learn about Fumadocs
6 changes: 6 additions & 0 deletions apps/docs/app/(home)/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { HomeLayout } from 'fumadocs-ui/layouts/home';
import { baseOptions } from '@/lib/layout.shared';

export default function Layout({ children }: LayoutProps<'/'>) {
Comment on lines +3 to +4
Copy link

Copilot AI Feb 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This layout signature uses LayoutProps<'/'> but there’s no local/imported definition for LayoutProps in the repo. Unless generated route types exist at build time, tsc/CI will fail. Consider using a plain { children: React.ReactNode } prop type (or importing a stable type) instead.

Suggested change
export default function Layout({ children }: LayoutProps<'/'>) {
import type { ReactNode } from 'react';
export default function Layout({ children }: { children: ReactNode }) {

Copilot uses AI. Check for mistakes.
return <HomeLayout {...baseOptions()}>{children}</HomeLayout>;
}
27 changes: 27 additions & 0 deletions apps/docs/app/(home)/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import Link from 'next/link';

export default function HomePage() {
return (
<div className="flex flex-col justify-center text-center flex-1 px-4">
<h1 className="text-4xl font-bold mb-4">ObjectStack Mobile</h1>
<p className="text-lg text-fd-muted-foreground mb-8 max-w-2xl mx-auto">
Enterprise-grade mobile runtime for the ObjectStack low-code platform.
Metadata-driven, offline-first, built with Expo &amp; React Native.
</p>
<div className="flex flex-row gap-4 justify-center">
<Link
href="/docs"
className="inline-flex items-center justify-center rounded-lg bg-fd-primary px-6 py-3 text-sm font-medium text-fd-primary-foreground shadow hover:bg-fd-primary/90"
>
Get Started
</Link>
<Link
href="/docs/hooks"
className="inline-flex items-center justify-center rounded-lg border border-fd-border px-6 py-3 text-sm font-medium shadow-sm hover:bg-fd-accent"
>
API Reference
</Link>
</div>
</div>
);
}
7 changes: 7 additions & 0 deletions apps/docs/app/api/search/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { source } from '@/lib/source';
import { createFromSource } from 'fumadocs-core/search/server';

export const { GET } = createFromSource(source, {
// https://docs.orama.com/docs/orama-js/supported-languages
language: 'english',
});
57 changes: 57 additions & 0 deletions apps/docs/app/docs/[[...slug]]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { getPageImage, source } from '@/lib/source';
import { DocsBody, DocsDescription, DocsPage, DocsTitle } from 'fumadocs-ui/layouts/docs/page';
import { notFound } from 'next/navigation';
import { getMDXComponents } from '@/mdx-components';
import type { Metadata } from 'next';
import { createRelativeLink } from 'fumadocs-ui/mdx';
import { LLMCopyButton, ViewOptions } from '@/components/ai/page-actions';
import { gitConfig } from '@/lib/layout.shared';

export default async function Page(props: PageProps<'/docs/[[...slug]]'>) {
const params = await props.params;
const page = source.getPage(params.slug);
Comment on lines +10 to +12
Copy link

Copilot AI Feb 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file uses PageProps<'/docs/[[...slug]]'> but there’s no local/imported definition for PageProps in the repo. Unless next typegen has been run and its generated types are available, tsc/CI will fail with an unknown identifier. Prefer using explicit props typing (e.g., { params: { slug?: string[] } }) or importing a stable type instead of relying on generated globals.

Copilot uses AI. Check for mistakes.
if (!page) notFound();

const MDX = page.data.body;

return (
<DocsPage toc={page.data.toc} full={page.data.full}>
<DocsTitle>{page.data.title}</DocsTitle>
<DocsDescription className="mb-0">{page.data.description}</DocsDescription>
<div className="flex flex-row gap-2 items-center border-b pb-6">
<LLMCopyButton markdownUrl={`${page.url}.mdx`} />
<ViewOptions
markdownUrl={`${page.url}.mdx`}
// update it to match your repo
githubUrl={`https://github.com/${gitConfig.user}/${gitConfig.repo}/blob/${gitConfig.branch}/apps/docs/content/docs/${page.path}`}
/>
Comment on lines +23 to +27
Copy link

Copilot AI Feb 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The generated GitHub URL is missing the apps/docs/ prefix. The content in this repo lives under apps/docs/content/docs/..., but the link points to .../content/docs/..., which will 404 on GitHub.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in abd0517. Added apps/docs/ prefix to the GitHub URL path.

</div>
<DocsBody>
<MDX
components={getMDXComponents({
// this allows you to link to other pages with relative file paths
a: createRelativeLink(source, page),
})}
/>
</DocsBody>
</DocsPage>
);
}

export async function generateStaticParams() {
return source.generateParams();
}

export async function generateMetadata(props: PageProps<'/docs/[[...slug]]'>): Promise<Metadata> {
const params = await props.params;
const page = source.getPage(params.slug);
if (!page) notFound();

return {
title: page.data.title,
description: page.data.description,
openGraph: {
images: getPageImage(page).url,
},
};
}
11 changes: 11 additions & 0 deletions apps/docs/app/docs/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { source } from '@/lib/source';
import { DocsLayout } from 'fumadocs-ui/layouts/docs';
import { baseOptions } from '@/lib/layout.shared';

export default function Layout({ children }: LayoutProps<'/docs'>) {
Comment on lines +4 to +5
Copy link

Copilot AI Feb 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This layout signature uses LayoutProps<'/docs'> but there’s no local/imported definition for LayoutProps in the repo. Unless generated route types exist at build time, tsc/CI will fail. Consider using a plain { children: React.ReactNode } prop type (or importing a stable type) to avoid depending on generated globals.

Suggested change
export default function Layout({ children }: LayoutProps<'/docs'>) {
import type React from 'react';
export default function Layout({ children }: { children: React.ReactNode }) {

Copilot uses AI. Check for mistakes.
return (
<DocsLayout tree={source.getPageTree()} {...baseOptions()}>
{children}
</DocsLayout>
);
}
3 changes: 3 additions & 0 deletions apps/docs/app/global.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
@import 'tailwindcss';
@import 'fumadocs-ui/css/neutral.css';
@import 'fumadocs-ui/css/preset.css';
12 changes: 12 additions & 0 deletions apps/docs/app/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { RootProvider } from 'fumadocs-ui/provider/next';
import './global.css';

export default function Layout({ children }: LayoutProps<'/'>) {
return (
<html lang="en" suppressHydrationWarning>
<body className="flex flex-col min-h-screen">
<RootProvider>{children}</RootProvider>
</body>
Copy link

Copilot AI Feb 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This layout signature uses LayoutProps<'/'> but there’s no local/imported definition for LayoutProps in the repo. Unless generated route types exist at build time, tsc/CI will fail. Consider using a plain { children: React.ReactNode } prop type (or importing a stable type) instead.

Copilot uses AI. Check for mistakes.
</html>
);
}
10 changes: 10 additions & 0 deletions apps/docs/app/llms-full.txt/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { getLLMText, source } from '@/lib/source';

export const revalidate = false;

export async function GET() {
const scan = source.getPages().map(getLLMText);
const scanned = await Promise.all(scan);

return new Response(scanned.join('\n\n'));
}
20 changes: 20 additions & 0 deletions apps/docs/app/llms.mdx/docs/[[...slug]]/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { getLLMText, source } from '@/lib/source';
import { notFound } from 'next/navigation';

export const revalidate = false;

export async function GET(_req: Request, { params }: RouteContext<'/llms.mdx/docs/[[...slug]]'>) {
const { slug } = await params;
const page = source.getPage(slug);
Comment on lines +6 to +8
Copy link

Copilot AI Feb 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

RouteContext<'/llms.mdx/docs/[[...slug]]'> is used but there’s no local/imported definition for RouteContext in the repo. Unless generated route types exist at build time, tsc/CI will fail. Consider typing the context as { params: { slug?: string[] } } (or similar) to avoid depending on generated globals.

Copilot uses AI. Check for mistakes.
if (!page) notFound();

return new Response(await getLLMText(page), {
headers: {
'Content-Type': 'text/markdown',
},
});
}

export function generateStaticParams() {
return source.generateParams();
}
13 changes: 13 additions & 0 deletions apps/docs/app/llms.txt/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { source } from '@/lib/source';

export const revalidate = false;

export async function GET() {
const lines: string[] = [];
lines.push('# Documentation');
lines.push('');
for (const page of source.getPages()) {
lines.push(`- [${page.data.title}](${page.url}): ${page.data.description}`);
}
return new Response(lines.join('\n'));
}
26 changes: 26 additions & 0 deletions apps/docs/app/og/docs/[...slug]/route.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { getPageImage, source } from '@/lib/source';
import { notFound } from 'next/navigation';
import { ImageResponse } from 'next/og';
import { generate as DefaultImage } from 'fumadocs-ui/og';

export const revalidate = false;

export async function GET(_req: Request, { params }: RouteContext<'/og/docs/[...slug]'>) {
const { slug } = await params;
const page = source.getPage(slug.slice(0, -1));
Comment on lines +8 to +10
Copy link

Copilot AI Feb 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

RouteContext<'/og/docs/[...slug]'> is used but there’s no local/imported definition for RouteContext in the repo. Unless generated route types exist at build time, tsc/CI will fail. Consider using the standard Next route handler context typing (e.g. { params: { slug: string[] } }) instead of relying on generated globals.

Copilot uses AI. Check for mistakes.
if (!page) notFound();

return new ImageResponse(
<DefaultImage title={page.data.title} description={page.data.description} site="ObjectStack Mobile" />,
{
Comment on lines +13 to +15
Copy link

Copilot AI Feb 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The OG image uses site="My App", which doesn’t match this project’s branding and will appear in link previews. Consider using the actual site/app name (e.g., “ObjectStack Mobile”) or pulling it from a shared constant/config.

Copilot uses AI. Check for mistakes.
width: 1200,
height: 630,
},
);
}

export function generateStaticParams() {
return source.getPages().map((page) => ({
slug: getPageImage(page).segments,
}));
Comment on lines +22 to +25
Copy link

Copilot AI Feb 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

generateStaticParams() returns an object with a lang key, but the route only has a single dynamic segment ([...slug]). Extra keys can cause Next to error during static generation. Return only { slug: ... } here (or add a matching [lang] segment if locales are intended).

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in abd0517. Removed the extra lang key — generateStaticParams() now returns only { slug } matching the [...slug] segment.

}
Loading