diff --git a/.github/workflows/check-links.yml b/.github/workflows/check-links.yml new file mode 100644 index 000000000..a652bdc74 --- /dev/null +++ b/.github/workflows/check-links.yml @@ -0,0 +1,30 @@ +name: Check Links + +on: + push: + branches: + - main + pull_request: + +jobs: + check-links: + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Check links with Lychee + uses: lycheeverse/lychee-action@v1 + with: + # Scan all markdown files in docs directory and README + args: | + --verbose + --no-progress + --config lychee.toml + 'docs/**/*.md' + 'docs/**/*.mdx' + 'README.md' + # Fail the action on broken links + fail: true + env: + GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}} diff --git a/.lycheeignore b/.lycheeignore new file mode 100644 index 000000000..7ccb2caa3 --- /dev/null +++ b/.lycheeignore @@ -0,0 +1,9 @@ +# Ignore localhost links (development/testing) +http://localhost* + +# Ignore example links +https://example.com + +# Ignore social media links (anti-scraping measures) +https://twitter.com* +https://x.com* diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 996422725..f52a5ecfa 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -400,14 +400,14 @@ Our repository includes several automated GitHub workflows that will run when yo ### Writing Documentation -We use VitePress for documentation. All docs are in `docs/`. +We use fumadocs for documentation. All docs are in `docs/`. ```bash # Start docs dev server -pnpm docs:dev +pnpm site:dev # Build docs -pnpm docs:build +pnpm site:build ``` ### Documentation Guidelines @@ -419,6 +419,42 @@ pnpm docs:build - Add practical, real-world examples - Link to related documentation +### Documentation Link Conventions + +**IMPORTANT**: When adding internal links in documentation, follow these conventions to avoid 404 errors: + +#### ✅ Correct Link Patterns + +```markdown + +[Quick Start](/docs/guide/quick-start) +[Components](/docs/components) +[API Reference](/docs/reference/api/core) +[Protocol Specs](/docs/reference/protocol/overview) +[Architecture](/docs/architecture/component) +``` + +#### ❌ Incorrect Link Patterns + +```markdown + +[Quick Start](/guide/quick-start) +[Components](/components) + + +[API Reference](/api/core) +[Spec](/spec/component) +[Protocol](/protocol/form) +``` + +#### Why? + +Fumadocs is configured with `baseUrl: '/docs'`, which means all documentation pages are served under the `/docs` route in Next.js. Internal links must include the `/docs/` prefix to match the actual URL structure where the pages are accessible. + +#### Validating Links + +Link validation runs automatically via GitHub Actions on all PRs using lychee-action. This checks for broken internal and external links. + See [Documentation Guide](./docs/README.md) for details. ## Versioning and Releases diff --git a/docs/index.md b/docs/index.md index 605aef47f..13958f0e9 100644 --- a/docs/index.md +++ b/docs/index.md @@ -10,13 +10,13 @@ hero: actions: - theme: brand text: Get Started - link: /guide/quick-start + link: /docs/guide/quick-start - theme: alt text: View Components - link: /components/ + link: /docs/components/ - theme: alt text: Read Docs - link: /guide/ + link: /docs/guide/ features: - title: 🎨 The Stack You Love @@ -30,21 +30,21 @@ features: ## Quick Links ### For Users -- 📖 [**Quick Start**](/guide/quick-start) - Get started in 5 minutes -- 🎨 [**Showcase**](/guide/showcase) - See all 60+ components in action -- 📦 [**Installation**](/guide/installation) - Setup instructions -- 🧩 [**Components**](/components/) - Component library reference +- 📖 [**Quick Start**](/docs/guide/quick-start) - Get started in 5 minutes +- 🎨 [**Showcase**](/docs/guide/showcase) - See all 60+ components in action +- 📦 [**Installation**](/docs/guide/installation) - Setup instructions +- 🧩 [**Components**](/docs/components/) - Component library reference ### For Developers -- 🤝 [**Contributing Guide**](/community/contributing) - How to contribute -- 📚 [**Architecture**](/architecture/architecture) - Technical architecture -- 🔧 [**API Reference**](/reference/api/core) - Complete API docs -- 🗺️ [**Roadmap**](/community/roadmap) - Upcoming features +- 🤝 [**Contributing Guide**](/docs/community/contributing) - How to contribute +- 📚 [**Architecture**](/docs/architecture/architecture) - Technical architecture +- 🔧 [**API Reference**](/docs/reference/api/core) - Complete API docs +- 🗺️ [**Roadmap**](/docs/community/roadmap) - Upcoming features ### Need Help? -- ❓ [**FAQ**](/faq) - Frequently asked questions -- 🔧 [**Troubleshooting**](/troubleshooting) - Common issues and solutions -- 🔒 [**Security**](/security) - Security best practices +- ❓ [**FAQ**](/docs/faq) - Frequently asked questions +- 🔧 [**Troubleshooting**](/docs/troubleshooting) - Common issues and solutions +- 🔒 [**Security**](/docs/security) - Security best practices - 💬 [**Discussions**](https://github.com/objectstack-ai/objectui/discussions) - Ask questions --- @@ -145,7 +145,7 @@ cd my-admin objectui dev ``` -[**📖 CLI Guide →**](/guide/cli/getting-started) +[**📖 CLI Guide →**](/docs/guide/cli/getting-started) ### Option B: React Library @@ -173,7 +173,7 @@ function App() { } ``` -[**📖 Installation Guide →**](/guide/installation) +[**📖 Installation Guide →**](/docs/guide/installation) --- @@ -181,58 +181,58 @@ function App() { ### 📘 Getting Started Start here if you're new to ObjectUI -- [Quick Start](/guide/quick-start) -- [Installation](/guide/installation) -- [Showcase](/guide/showcase) +- [Quick Start](/docs/guide/quick-start) +- [Installation](/docs/guide/installation) +- [Showcase](/docs/guide/showcase) ### 🧩 Components Browse all available components -- [Component Gallery](/components/) -- [Form Components](/components/form/) -- [Layout Components](/components/layout/) +- [Component Gallery](/docs/components/) +- [Form Components](/docs/components/form/) +- [Layout Components](/docs/components/layout/) ### 💡 Core Concepts Understand how ObjectUI works -- [Schema Rendering](/concepts/schema-rendering) -- [Expressions](/concepts/expressions) -- [Data Sources](/concepts/data-source) +- [Schema Rendering](/docs/concepts/schema-rendering) +- [Expressions](/docs/concepts/expressions) +- [Data Sources](/docs/concepts/data-source) ### 🔌 Plugins Extend ObjectUI with plugins -- [Plugin System](/concepts/plugins) -- [Charts Plugin](/plugins/plugin-charts) -- [Kanban Plugin](/plugins/plugin-kanban) +- [Plugin System](/docs/concepts/plugins) +- [Charts Plugin](/docs/plugins/plugin-charts) +- [Kanban Plugin](/docs/plugins/plugin-kanban) ### 📚 Reference Detailed API documentation -- [Core API](/reference/api/core) -- [React API](/reference/api/react) -- [Protocol Specifications](/reference/protocol/overview) +- [Core API](/docs/reference/api/core) +- [React API](/docs/reference/api/react) +- [Protocol Specifications](/docs/reference/protocol/overview) ### 🏗️ Architecture For contributors and advanced users -- [System Architecture](/architecture/architecture) -- [Project Structure](/architecture/project-structure) -- [Component Specs](/architecture/component) +- [System Architecture](/docs/architecture/architecture) +- [Project Structure](/docs/architecture/project-structure) +- [Component Specs](/docs/architecture/component) ### 🌐 Ecosystem Integration and deployment -- [ObjectQL Integration](/ecosystem/objectql) -- [API Integration](/ecosystem/api) -- [Deployment Guide](/ecosystem/deployment/showcase-deployment) +- [ObjectQL Integration](/docs/ecosystem/objectql) +- [API Integration](/docs/ecosystem/api) +- [Deployment Guide](/docs/ecosystem/deployment/showcase-deployment) ### 🆘 Support Get help when you need it -- [FAQ](/faq) - Common questions -- [Troubleshooting](/troubleshooting) - Problem solving -- [Security](/security) - Security best practices -- [Migration](/migration/from-objectstack) - Migration guides +- [FAQ](/docs/faq) - Common questions +- [Troubleshooting](/docs/troubleshooting) - Problem solving +- [Security](/docs/security) - Security best practices +- [Migration](/docs/migration/from-objectstack) - Migration guides ### 🤝 Community Contribute and collaborate -- [Contributing](/community/contributing) -- [Roadmap](/community/roadmap) -- [Best Practices](/community/best-practices) +- [Contributing](/docs/community/contributing) +- [Roadmap](/docs/community/roadmap) +- [Best Practices](/docs/community/best-practices) --- @@ -241,8 +241,8 @@ Contribute and collaborate Stop writing repetitive UI code. Start building with ObjectUI.
diff --git a/docs/plugins/plugin-markdown.mdx b/docs/plugins/plugin-markdown.mdx index e64d2328a..f6700eb11 100644 --- a/docs/plugins/plugin-markdown.mdx +++ b/docs/plugins/plugin-markdown.mdx @@ -189,7 +189,7 @@ npm install our-package 2. Configure your settings 3. Start building! -For more information, see the [API Reference](/api). +For more information, see the [API Reference](/docs/reference/api/core). `, className: 'prose prose-lg max-w-none' } @@ -230,7 +230,7 @@ app.run() ## Contributing -Contributions are welcome! Please read our [contributing guidelines](CONTRIBUTING.md). +Contributions are welcome! Please read our [contributing guidelines](https://github.com/objectstack-ai/objectui/blob/main/CONTRIBUTING.md). ## License diff --git a/docs/plugins/plugin-object.mdx b/docs/plugins/plugin-object.mdx index afee8a5af..3713d7f0d 100644 --- a/docs/plugins/plugin-object.mdx +++ b/docs/plugins/plugin-object.mdx @@ -539,7 +539,7 @@ const dataSource = new ObjectQLDataSource({ ## Related Documentation -- [ObjectQL Integration](/docs/ecosystem/objectql.md) -- [Data Sources](/docs/concepts/data-source.md) +- [ObjectQL Integration](/docs/ecosystem/objectql) +- [Data Sources](/docs/concepts/data-source) - [Plugin System Overview](/docs/concepts/plugins) - [Package README](https://github.com/objectstack-ai/objectui/tree/main/packages/plugin-object) diff --git a/lychee.toml b/lychee.toml new file mode 100644 index 000000000..0dbfe78c6 --- /dev/null +++ b/lychee.toml @@ -0,0 +1,48 @@ +# Lychee configuration file for ObjectUI documentation link checking +# This configuration enables checking internal fumadocs links by mapping +# Next.js routes (e.g., /docs/guide) to filesystem paths (e.g., docs/guide.mdx) + +# Maximum number of concurrent requests +max_concurrency = 10 + +# Timeout for each request (in seconds) +timeout = 20 + +# Number of retries per request +max_retries = 3 + +# Accept any valid status code (2xx, 3xx) +accept = [200, 204, 206, 301, 302, 303, 307, 308] + +# Exclude patterns - files and URLs to skip +exclude = [ + # Local development URLs + "http://localhost*", + "https://localhost*", + + # Example and placeholder URLs + "https://example.com", + "http://example.com", + + # Social media (anti-scraping) + "https://twitter.com*", + "https://x.com*", + + # GitHub specific patterns that may cause false positives + "https://github.com/.*/compare/*", + "https://github.com/.*/commit/*", +] + +# Path remapping for fumadocs internal links +# Maps Next.js routes to actual file paths +# Format: ["pattern to match", "replacement"] +remap = [ + # Map /docs/* links to docs/ filesystem paths + # The file:// prefix tells lychee to check local files + "^/docs/(.*)$ file://./docs/$1" +] + +# Cache configuration +[cache] +# Don't use cache to ensure fresh results +max_age = "0s"