add category index pages and improve docs navigation structure#67
add category index pages and improve docs navigation structure#67tjyyy3 wants to merge 1 commit intocasbin:masterfrom
Conversation
✅ Deploy Preview for casbin-website-v3 ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
|
@tjyyy3 is attempting to deploy a commit to the Antony's projects Team on Vercel. A member of the Team first needs to authorize it. |
There was a problem hiding this comment.
Pull request overview
This PR adds category index pages for documentation and restructures the navigation to improve user experience. The changes introduce dynamic category pages that display all documentation pages within each section as cards, along with navigation improvements including clickable category separators in the sidebar.
Changes:
- Added category index page infrastructure with dynamic routing at
/docs/category/[...slug] - Renamed documentation directory from
basics/tothe-basics/for consistency - Restructured RBAC and MAC documentation by consolidating overview pages into
index.mdxfiles
Reviewed changes
Copilot reviewed 29 out of 33 changed files in this pull request and generated 11 comments.
Show a summary per file
| File | Description |
|---|---|
| src/lib/source.ts | Added categoryPageConfigs mapping, subcategory configurations, and helper functions; removed custom slug flattening |
| src/components/sidebar/separator.tsx | New component to render category separators as clickable links in the sidebar |
| src/components/docs/PrevNext.tsx | New navigation component for previous/next page links |
| src/app/docs/category/[...slug]/page.tsx | Dynamic category page component that displays all pages in a category as cards |
| src/app/docs/layout.tsx | Updated sidebar configuration and added custom separator component |
| source.config.ts | Extended frontmatter schema with slug and icon fields |
| content/docs/meta.json | Restructured to use separator syntax for better navigation grouping |
| content/docs/the-basics/* | New directory with overview, get-started, how-it-works, and tutorial pages |
| content/docs/model/rbac/index.mdx | Consolidated RBAC overview into index.mdx (removed rbac-overview.mdx) |
| content/docs/model/mac/index.mdx | Consolidated MAC overview into index.mdx (removed mac-overview.mdx) |
| content/docs/plugins/middlewares/index.mdx | Renamed from middlewares.mdx to index.mdx |
| content/docs/api/index-api.mdx | New overview page for API category (duplicate content concern) |
| Various _meta.json files | Consistency updates to title/pages ordering |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| // This replaces the hardcoded categoryPageMappings in the category page component | ||
| export const categoryPageConfigs: Record<string, string[]> = { | ||
| "the-basics": [ | ||
| "the-basics/overview", |
There was a problem hiding this comment.
The page slug "the-basics/overview" is inconsistent with the _meta.json configuration. The file content/docs/the-basics/_meta.json references "index" as the first page, but there is no index.mdx file in that directory. The actual file is overview.mdx. Either:
- Change this line to "the-basics/index" if overview.mdx should be treated as the index, or
- Update content/docs/the-basics/_meta.json to reference "overview" instead of "index"
This inconsistency may cause the getCategoryPages function to fail to find this page.
| "plugins/watchers", | ||
| "plugins/dispatchers", | ||
| "plugins/role-managers", | ||
| "plugins/middlewares", |
There was a problem hiding this comment.
The reference to "plugins/middlewares" (line 67) should likely be "plugins/middlewares/index" to match the renamed file structure where middlewares.mdx was renamed to index.mdx. This inconsistency may cause getCategoryPages to fail to find this page.
| {/* Navigation, Feedback, and Comments */} | ||
| <div className="mt-12 pt-8"> | ||
| <Feedback onSendAction={onPageFeedbackAction} /> | ||
| <PrevNext pages={categoryPages} currentUrl={`/docs/${categoryName}`} /> |
There was a problem hiding this comment.
The PrevNext component is being passed a currentUrl of /docs/${categoryName} (e.g., "/docs/the-basics"), but categoryPages contains URLs like "/docs/the-basics/overview", "/docs/the-basics/get-started", etc. The currentUrl will never match any page in the pages array, causing currentIndex to always be -1. This means the PrevNext navigation will not work correctly on category pages. Consider removing the PrevNext component from category pages since they are index pages listing other pages, or adjust the logic to handle this scenario differently.
| const categoryUrls: Record<string, string> = { | ||
| "The basics": "/docs/category/the-basics", | ||
| Model: "/docs/category/model", | ||
| Storage: "/docs/category/storage", | ||
| Scenarios: "/docs/category/scenarios", | ||
| Plugins: "/docs/category/plugins", | ||
| API: "/docs/category/api", | ||
| "Advanced usage": "/docs/category/advanced-usage", | ||
| Management: "/docs/category/management", | ||
| Editor: "/docs/category/editor", | ||
| More: "/docs/category/more", | ||
| }; |
There was a problem hiding this comment.
The hardcoded categoryUrls mapping in this component duplicates the logic found in categoryPageConfigs in src/lib/source.ts and categoryDisplayNames in src/app/docs/category/[...slug]/page.tsx. This creates a maintenance burden where changes to category slugs would need to be updated in multiple places. Consider exporting the category URL mapping from a single source (such as source.ts) and importing it here to maintain a single source of truth.
| export function getSubCategoryItemCount(relativePath: string): number { | ||
| for (const pages of Object.values(categoryPageConfigs)) { | ||
| if (pages.includes(relativePath)) { | ||
| const parentPath = relativePath; | ||
| return pages.filter((path) => path.startsWith(parentPath + "/") || path === parentPath) | ||
| .length; | ||
| } | ||
| } | ||
| return 0; | ||
| } |
There was a problem hiding this comment.
The getSubCategoryItemCount function has a logic issue. It searches for pages that include the relativePath, then uses that same relativePath as the parentPath to count items. However, it will return the count from the first category that contains the page, not necessarily the correct category. For example, if "model/rbac" exists in the "model" category array, the function will count items in the entire model category, not just the RBAC subcategory. This could lead to incorrect item counts being displayed. Consider refactoring to explicitly search within the correct category or improve the logic to identify the proper parent category.
| "model/rbac", | ||
| "model/rbac/rbac", | ||
| "model/rbac/rbac-with-pattern", | ||
| "model/rbac/rbac-with-domains", | ||
| "model/rbac/rbac-with-conditions", | ||
| "model/rbac/casbin-rbac-and-rbac96", | ||
| "model/mac", |
There was a problem hiding this comment.
The references to "model/rbac" (line 47) and "model/mac" (line 53) appear to be referencing overview pages for these subcategories. However, based on the updated _meta.json files, these should reference "model/rbac/index" and "model/mac/index" instead since the files were renamed from rbac-overview.mdx/mac-overview.mdx to index.mdx. This inconsistency may cause getCategoryPages to not find these pages correctly.
| --- | ||
| id: overview | ||
| title: Overview | ||
| description: Casbin Overview | ||
| keywords: [overview, supported languages] | ||
| authors: [hsluoyz] | ||
| --- | ||
|
|
||
| Casbin is an efficient, open-source access control library designed to enforce authorization through support for multiple [access control models](https://en.wikipedia.org/wiki/Access_control#Access_control_models). | ||
|
|
||
| Implementing rule-based access control is straightforward: define subjects, objects, and permitted actions in a **_policy_** file using any format that suits your requirements. This pattern remains consistent throughout all Casbin implementations. Through the **_model_** file, developers and administrators maintain full authority over authorization logic, including layout, execution flow, and conditional requirements. To validate incoming requests against your defined policy and model files, Casbin provides an **_Enforcer_** component. | ||
|
|
||
| ## Languages Supported by Casbin | ||
|
|
||
| Casbin offers native support across multiple programming languages, enabling seamless integration into diverse projects and workflows: | ||
|
|
||
| | [](https://github.com/casbin/casbin) | [](https://github.com/casbin/jcasbin) | [](https://github.com/casbin/node-casbin) | [](https://github.com/php-casbin/php-casbin) | | ||
| |----------------------------------------------------------------------|-------------------------------------------------------------------|---------------------------------------------------------------------------|------------------------------------------------------------------------| | ||
| | [Casbin](https://github.com/casbin/casbin) | [jCasbin](https://github.com/casbin/jcasbin) | [node-Casbin](https://github.com/casbin/node-casbin) | [PHP-Casbin](https://github.com/php-casbin/php-casbin) | | ||
| | Production-ready | Production-ready | Production-ready | Production-ready | | ||
|
|
||
| | [](https://github.com/casbin/pycasbin) | [](https://github.com/casbin/Casbin.NET) | [](https://github.com/casbin/casbin-cpp) | [](https://github.com/casbin/casbin-rs) | | ||
| |------------------------------------------------------------------------|--------------------------------------------------------------------------|--------------------------------------------------------------------|---------------------------------------------------------------------| | ||
| | [PyCasbin](https://github.com/casbin/pycasbin) | [Casbin.NET](https://github.com/casbin/Casbin.NET) | [Casbin-CPP](https://github.com/casbin/casbin-cpp) | [Casbin-RS](https://github.com/casbin/casbin-rs) | | ||
| | Production-ready | Production-ready | Production-ready | Production-ready | | ||
|
|
||
| ### Feature Set for Different Languages | ||
|
|
||
| Our goal is feature parity across all language implementations, though we haven't achieved complete uniformity yet. | ||
|
|
||
| Feature | Go | Java | Node.js | PHP | Python | C# | Delphi | Rust | C++ | Lua | Dart | Elixir | ||
| :--- | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--:| :--: | :--: | :--: | ||
| Enforcement | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ||
| RBAC | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ||
| ABAC | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ||
| Scaling ABAC (`eval()`) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ | ||
| Adapter | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ||
| Management API | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ||
| RBAC API | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ||
| Batch API | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | ✅ | ❌ | ❌ | ||
| Filtered Adapter | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | ✅ | ❌ | ❌ | ||
| Watcher | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ||
| Role Manager | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | ✅ | ✅ | ❌ | ||
| Multi-Threading | ✅ | ✅ | ✅ | ❌ | ✅ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ||
| 'in' of matcher | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ | ❌ | ❌ | ❌ | ✅ | ✅ | ||
|
|
||
| **Note** - A checkmark (✅) for Watcher or Role Manager indicates that the interface exists in the core library, not necessarily that an implementation is available. | ||
|
|
||
| ## What is Casbin? | ||
|
|
||
| Casbin serves as an authorization library for scenarios requiring controlled access to resources. In typical usage, a `subject` (user or service) requests access to an `object` (resource or entity) to perform an `action` (such as _read_, _write_, or _delete_). Developers define these actions according to their application needs. This represents the "standard" or classic `{ subject, object, action }` authorization flow that Casbin handles most commonly. | ||
|
|
||
| Beyond this standard model, Casbin accommodates complex authorization scenarios by supporting [roles (RBAC)](/docs/rbac), [attributes (ABAC)](/docs/abac), and other advanced patterns. | ||
|
|
||
| ### What Casbin Does | ||
|
|
||
| 1. Applies policy enforcement in the classic ``{ subject, object, action }`` format or any custom format you define, supporting both allow and deny authorizations. | ||
| 2. Manages storage for the access control model and associated policies. | ||
| 3. Handles user-role and role-role relationships (the role hierarchy concept in RBAC). | ||
| 4. Recognizes built-in superusers such as ``root`` or ``administrator`` who have unrestricted access without requiring explicit permission rules. | ||
| 5. Supplies various built-in operators for pattern matching in rules—for instance, ``keyMatch`` matches resource key ``/foo/bar`` to pattern ``/foo*``. | ||
|
|
||
| ### What Casbin Does **NOT** Do | ||
|
|
||
| 1. User authentication (validating ``username`` and ``password`` credentials during login) | ||
| 2. User or role list management | ||
|
|
||
| Most applications already manage their own user accounts, roles, and credentials. Casbin wasn't designed as a password storage system—it focuses solely on authorization. That said, Casbin does maintain user-role associations when operating in RBAC mode. |
There was a problem hiding this comment.
This file appears to be a duplicate of content/docs/index.mdx and content/docs/the-basics/overview.mdx with identical content. Having the same overview content in multiple locations may cause confusion for users and create maintenance issues. Consider whether this file should have different API-specific content or if it's intended to be an index page for the API category. If it's meant as a category index, it might be better placed as a simple index listing API documentation pages rather than duplicating the general Casbin overview.
| import { usePathname } from "next/navigation"; | ||
| import { cn } from "@/lib/utils"; | ||
| import type { Separator } from "fumadocs-core/page-tree"; | ||
| import { useFolderDepth } from "fumadocs-ui/components/sidebar/base"; |
There was a problem hiding this comment.
The useFolderDepth import is unused in this component. This import should be removed to clean up the code.
| export const source = loader({ | ||
| baseUrl: "/docs", | ||
| source: docs.toFumadocsSource(), | ||
| slugs: flattenDocSlugs, | ||
| plugins: [lucideIconsPlugin()], | ||
| icon(icon) { | ||
| if (!icon) return; | ||
| if (icon in icons) return createElement(icons[icon as keyof typeof icons]); | ||
| }, | ||
| }); |
There was a problem hiding this comment.
The removal of the custom slugs function (flattenDocSlugs) will change how document URLs are generated by fumadocs. Previously, folder names were kept out of the pathname (flattened), but now fumadocs will use its default behavior which typically includes the full folder path. This change will affect all existing URLs in the documentation, potentially breaking:
- External links pointing to the old URL structure
- Internal cross-references in documentation
- Search engine indexing
- Bookmarks
Before merging, verify that:
- The new URL structure is intentional and acceptable
- All internal documentation links have been updated to match the new structure
- Appropriate redirects are in place for old URLs if this is a public-facing site
| "use client"; | ||
|
|
||
| import Link from "next/link"; | ||
| import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; |
There was a problem hiding this comment.
Unused import CardContent.
📝 Summary
This PR adds category index pages for the documentation and restructures the navigation to improve user experience.
✨ Changes Made
Added Category Index Pages
Documentation Structure Improvements
UI/UX Enhancements