diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000..cb22b12 Binary files /dev/null and b/.DS_Store differ diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..0cac9ce --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,329 @@ +## [1.8.0] - 2025-03-01 + +> Now looks more modern and clean which is a big change in layout and design + +### Added + +- Social footer +- Toggle group +- Site description {meta.description} in footer +- Site title {meta.title} in footer + +### Improved + +- Header design changes +- Footer design changes +- New functions in theme provider +- Object changes in docu.json + +### Fixed + +- Updates to path structure components +- Groups to organize components + +## [1.7.0] - 2025-02-23 + +> Remove the old function in the search dialog and replace it with a new and more optimal feature + +### Added + +- Up and down navigation : search dialog.tsx +- Enter (return) to select : search dialog.tsx +- Escape to close the dialog : search dialog.tsx + +### Improved + +- Maintenance for anchor components +- Anchor.tsx adjustments for all elements that use it + +### Removed + +- Remove suboptimal search features + +## [1.6.0] - 2025-02-21 + +> New Feature Card Groups with arrays for more Flexible Content + +### Added + +- Card Groups Components +- Props : href to url link +- Props : horizontal boolean + +### Improved + +- Card props styling +- Compability for Cards components +- {children} support for card content + +### Removed + +- remove unused props cards components + +## [1.5.0] - 2025-02-18 + +> Minor Update - improved features and responsiveness on all devices + +### Added + +- New dialog footer on searchbox above @media 768px +- Icon X for close dialog on searcbox as esc on medium screen + +### Improved + +- Responsive Leftbar components on large screen +- Menu Trigger on medium screen +- Responsive Navbar components on medium screen +- Better UX for searchbox dialog +- tooltips components can be written together with regular paragraphs + +### Fixed + +- Responsive issue +- Compatibility for Bun +- Changes postcss.config.js to .cjs for Bun +- all CLI installer and updater not working +- adjustments for package managers npm, pnpm, bun, yarn + +## [1.4.2] - 2025-02-16 + +> Complex Content for Accordion Component props {children} + +### Added + +- New Props with {children} in accordion +- Compatibility for markdown in accordion +- Nested components inside an accordion +- New icon on note components +- add CLI npx @docubook/create@latest +- add CLI npx @docubook/update@latest + +### Improved + +- Better UI design for accordion +- Styling Note components on markdown +- Change accordion output on playground +- Change accordion output on snippet + +### Removed + +- Remove depcreated props on accordion +- Remove CLI npx update_docu +- Remove CLI npx create_docu + +## [1.4.0] - 2025-02-11 + +> Floating Button Version with Dynamic Tag {version} on Changelog page + +### Added + +- New components / changelog floating-version.tsx +- Button popover to open version-toc below @media 1024px +- Dynamic tag by section ID #version +- Dynamic url tag #version +- Dynamic version indicator on floating version when scrolling section by ID + +### Improved + +- change icon version history +- responsive version-toc +- improvement components to changelog page + +## [1.3.8] - 2025-02-08 + +> Responsive Table of Content + +### Added + +- Components terminal MagicUI +- Components card Shadcn +- New mob-toc for a better experience on mobile devices +- New Components scroll to top button +- Scroll to top :blog-post +- Scroll to top :docs-post + +### Improved + +- lib/markdown for generated dynamic toc on markdown +- Responsive Table of Content below @media 1024px +- Improve docs page + +## [1.3.6] - 2025-02-01 + +> Appears more modern editor for Docu Play + +![version 1.3.6 - Playground](https://docubook.pro/images/new-editor.png) + +### Added + +- Line Number for editor +- editor.css + +### Improved + +- Better Design for Editor +- Similar to Github Editor +- Moved Handler Element (copy, download, reset and fullscreen) on Header + +## [1.3.5] - 2025-01-30 + +> it's Easy to Write Markdown with Playground + +![version 1.3.5 - Playground](https://docubook.pro/images/img-playground.png) + +### Added + +- New Playground Page +- New Playground Layout +- Toolbar for Markdown Components +- Fullscreen Mode to Focus Editing Your Content +- Copy to Clipboard Your Content +- Download Your Content as index.mdx +- Reset Your Content without refresh the Browser +- Only Large Screen for Better Experience + +## [1.3.1] - 2025-01-20 + +> Snippet Feature to Easily Write Markdown and Call DocuBook Components + +![version 1.3.1 - Snippet Features](https://docubook.pro/images/snippet.png) + +### Added + +- New Feature Snippet for Markdown Components +- Support Snippet for Visual Studio Code + +### Removed + +- remove props icon and props description for accordion components + +## [1.3.0] - 2024-12-31 + +> Release Note Feature to Make it Easier to Write Changelogs + +### Added + +- New Release Note Feature +- New Layout for Changelog page +- New Changelog page +- Add Release Note Component +- Easily write release notes directly from the CHANGELOG.md file +- TOC for versioning +- Write with the markdown tag +- Add lib / changelog.ts + +### Improved + +- Improvement Responsive feature image for Version Entry +- Improvement Layout for changelog page +- Improvement Padding on mobile devices +- Only use containers of md size +- Improvement syntax.css for ul>li classes + +### Fixed + +- Fix og:image not showing on Page.tsx +- Fix text-indent on class li + +### Removed + +- Remove excessive padding +- Remove Logo on Footer + +## [1.2.0] - 2024-12-22 + +> New Accordion Component : Support content plain text, html and all markdown component + +### Added + +- add New Accordion + +### Improved + +- Props Improvement +- Support Dynamic Content for Accordion + +## [1.1.0] - 2024-12-15 + +> Minor Update : Easily manage set up with docu.json + +### Added + +- add docu.json file +- add openGraph (title, description, image) +- add Dynamic metadata +- Generate metadata as openGraph +- openGraph support for .mdx + +### Improved + +- routes-config from json +- Frontmatter improvement +- Edit the content of footer.tsx simply via the docu.json file +- Edit the content of navbar.tsx simply via the docu.json file + +## [1.0.7] - 2024-12-14 + +> Easily updates your DocuBook Version with CLI npx update_docu + +### Added + +- CLI npx update_docu (update features into docubook existing directory) +- Playground (easily to written content) +- New Button component +- Navbar external link conditions +- CLI npx create_docu + +### Improved + +- Searchbar Improvement +- Navigation Improvement +- Edit on Github Improvement + +### Removed +- Remove CLI npx create-docu (on this version not usage dash `-`) + +## [1.0.6] - 2024-11-24 + +> New Components, Fix and Improvement + +### Added + +- New Card component +- New Tooltips component + +### Fixed + +- change root folder + +### Improved + +- logo on navbar & footer +- easily change logo + +## [1.0.5] - 2024-11-16 + +> Add New Features and Improvement for this version + +### Added + +- New Youtube component +- edit this page - easily manage directory content via the github repo +- support installation via cli commant npx create-docu + +### Improved + +- keyboard shortcut command + k or ctrl + k to open search dialog + +## [1.0.0] - 2024-11-10 + +> Initial release of DocuBook to create interactive nested docs with MDX + +### Added + +- Initial release of DocuBook +- Basic documentation structure +- Markdown support with MDX +- Responsive design +- Search functionality +- Dark mode support diff --git a/README.md b/README.md new file mode 100644 index 0000000..3195f30 --- /dev/null +++ b/README.md @@ -0,0 +1,39 @@ +# DocuBook + +**DocuBook** is a documentation web project designed to provide a simple and user-friendly interface for accessing various types of documentation. This site is crafted for developers and teams who need quick access to references, guides, and essential documents. + +> **Note**: This application is a fork of [AriaDocs](https://github.com/nisabmohd/Aria-Docs), created by [Nisab Mohd](https://github.com/nisabmohd). DocuBook provides an alternative to the documentation solution found on [Mintlify](https://mintlify.com/), utilizing `.mdx` (Markdown + JSX) for content creation and management. + +[![Deploy with +Vercel](https://vercel.com/button)](https://vercel.com/import/project?template=https://github.com/gitfromwildan/docubook) + +## Features + +- **Easy Navigation**: Simple layout for quick navigation between pages. +- **Quick Search**: Easily find documentation using a search function. +- **Responsive Theme**: Responsive design optimized for devices ranging from desktops to mobile. +- **Markdown Content**: Support for markdown-based documents. +- **SEO Friendly**: Optimized structure for search visibility, enhancing accessibility on search engines. + +## Installation + +```bash +npx @docubook/create@latest +``` + +#### command output + +```bash +? Enter a name for your project directory: (docubook) + +Creating a new Docubook project in /path/your/docubook from the main branch... +✔ Docubook project successfully created in /path/your/docubook! + +Next steps: +1. Navigate to your project directory: + cd docubook +2. Install dependencies: + npm install +3. Start the development server: + npm run dev +``` diff --git a/app/.DS_Store b/app/.DS_Store new file mode 100644 index 0000000..a2b816d Binary files /dev/null and b/app/.DS_Store differ diff --git a/app/blog/.DS_Store b/app/blog/.DS_Store new file mode 100644 index 0000000..1e0c66d Binary files /dev/null and b/app/blog/.DS_Store differ diff --git a/app/blog/[slug]/page.tsx b/app/blog/[slug]/page.tsx new file mode 100644 index 0000000..42951bc --- /dev/null +++ b/app/blog/[slug]/page.tsx @@ -0,0 +1,92 @@ +import { Typography } from "@/components/typography"; +import { buttonVariants } from "@/components/ui/button"; +import { Author, getAllBlogStaticPaths, getBlogForSlug } from "@/lib/markdown"; +import { ArrowLeftIcon } from "lucide-react"; +import Link from "next/link"; +import { notFound } from "next/navigation"; +import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"; +import { formatDate } from "@/lib/utils"; +import { ScrollToTop } from "@/components/scroll-to-top"; + +type PageProps = { + params: { slug: string }; +}; + +export async function generateMetadata({ params: { slug } }: PageProps) { + const res = await getBlogForSlug(slug); + if (!res) return null; + const { frontmatter } = res; + return { + title: frontmatter.title, + description: frontmatter.description, + }; +} + +export async function generateStaticParams() { + const val = await getAllBlogStaticPaths(); + if (!val) return []; + return val.map((it) => ({ slug: it })); +} + +export default async function BlogPage({ params: { slug } }: PageProps) { + const res = await getBlogForSlug(slug); + if (!res) notFound(); + return ( +
+ + Back to blog + +
+

+ {formatDate(res.frontmatter.date)} +

+

+ {res.frontmatter.title} +

+
+

Posted by

+ +
+
+
+ {res.content} +
+ +
+ ); +} + +function Authors({ authors }: { authors: Author[] }) { + return ( +
+ {authors.map((author) => { + return ( + + + + + {author.username.slice(0, 2).toUpperCase()} + + +
+

{author.username}

+

+ @{author.handle} +

+
+ + ); + })} +
+ ); +} diff --git a/app/blog/layout.tsx b/app/blog/layout.tsx new file mode 100644 index 0000000..6211155 --- /dev/null +++ b/app/blog/layout.tsx @@ -0,0 +1,9 @@ +import { PropsWithChildren } from "react"; + +export default function BlogLayout({ children }: PropsWithChildren) { + return ( +
+ {children} +
+ ); +} diff --git a/app/blog/page.tsx b/app/blog/page.tsx new file mode 100644 index 0000000..780cd39 --- /dev/null +++ b/app/blog/page.tsx @@ -0,0 +1,98 @@ +import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"; +import { Author, BlogMdxFrontmatter, getAllBlogs } from "@/lib/markdown"; +import { formatDate2, stringToDate } from "@/lib/utils"; +import { getMetadata } from "@/app/layout"; +import Image from "next/image"; +import Link from "next/link"; +import docuConfig from "@/docu.json"; + +export const metadata = getMetadata({ + title: "Blog", + description: "Discover the latest updates, tutorials, and insights on DocuBook.", +}); +const { meta } = docuConfig; +export default async function BlogIndexPage() { + const blogs = (await getAllBlogs()).sort( + (a, b) => stringToDate(b.date).getTime() - stringToDate(a.date).getTime() + ); + return ( +
+
+

+ Blog Posts +

+

+ Discover the latest updates, tutorials, and insights on {meta.title}. +

+
+
+ {blogs.map((blog) => ( + + ))} +
+
+ ); +} + +function BlogCard({ + date, + title, + description, + slug, + cover, + authors, +}: BlogMdxFrontmatter & { slug: string }) { + return ( + +

{title}

+
+ {title} +
+

{description}

+
+

+ Published on {formatDate2(date)} +

+ +
+ + ); +} + +function AvatarGroup({ users, max = 4 }: { users: Author[]; max?: number }) { + const displayUsers = users.slice(0, max); + const remainingUsers = Math.max(users.length - max, 0); + + return ( +
+ {displayUsers.map((user, index) => ( + + + + {user.username.slice(0, 2).toUpperCase()} + + + ))} + {remainingUsers > 0 && ( + + +{remainingUsers} + + )} +
+ ); +} diff --git a/app/changelog/layout.tsx b/app/changelog/layout.tsx new file mode 100644 index 0000000..b77f34a --- /dev/null +++ b/app/changelog/layout.tsx @@ -0,0 +1,11 @@ +export default function ChangelogLayout({ + children, +}: { + children: React.ReactNode; +}) { + return ( +
+ {children} +
+ ); +} \ No newline at end of file diff --git a/app/changelog/page.tsx b/app/changelog/page.tsx new file mode 100644 index 0000000..397a039 --- /dev/null +++ b/app/changelog/page.tsx @@ -0,0 +1,63 @@ +import { Suspense } from "react"; +import { getChangelogEntries } from "@/lib/changelog"; +import { VersionEntry } from "@/components/changelog/version-entry"; +import { VersionToc } from "@/components/changelog/version-toc"; +import { getMetadata } from "@/app/layout"; +import docuConfig from "@/docu.json"; +import { FloatingVersionToc } from "@/components/changelog/floating-version"; + +export const metadata = getMetadata({ + title: "Changelog", + description: "Latest updates and improvements to DocuBook", + image: "release-note.png", +}); + +export default async function ChangelogPage() { + const entries = await getChangelogEntries(); + const { meta } = docuConfig; + return ( +
+
+
+

Changelog

+

+ Latest updates and improvements to {meta.title} +

+
+
+ +
+
+ }> + ({ version, date }))} + /> + + +
+
+
+
+ {entries.map((entry, index) => ( +
+ +
+ ))} +
+
+
+
+
+ {/* Floating TOC for smaller screens */} + {entries.length > 0 && ( + ({ version, date }))} + /> + )} +
+ ); +} diff --git a/app/docs/.DS_Store b/app/docs/.DS_Store new file mode 100644 index 0000000..6ed269c Binary files /dev/null and b/app/docs/.DS_Store differ diff --git a/app/docs/[[...slug]]/page.tsx b/app/docs/[[...slug]]/page.tsx new file mode 100644 index 0000000..6a2eeb6 --- /dev/null +++ b/app/docs/[[...slug]]/page.tsx @@ -0,0 +1,105 @@ +import { notFound } from "next/navigation"; +import { getDocsForSlug, getDocsTocs } from "@/lib/markdown"; +import DocsBreadcrumb from "@/components/docs-breadcrumb"; +import Pagination from "@/components/pagination"; +import Toc from "@/components/toc"; +import { Typography } from "@/components/typography"; +import EditThisPage from "@/components/edit-on-github"; +import { formatDate2 } from "@/lib/utils"; +import docuConfig from "@/docu.json"; +import MobToc from "@/components/mob-toc"; +import { ScrollToTop } from "@/components/scroll-to-top"; + +const { meta } = docuConfig; + +type PageProps = { + params: { + slug: string[]; + }; +}; + +// Function to generate metadata dynamically +export async function generateMetadata({ params: { slug = [] } }: PageProps) { + const pathName = slug.join("/"); + const res = await getDocsForSlug(pathName); + + if (!res) { + return { + title: "Page Not Found", + description: "The requested page was not found.", + }; + } + + const { title, description, image } = res.frontmatter; + + // Absolute URL for og:image + const ogImage = image + ? `${meta.baseURL}/images/${image}` + : `${meta.baseURL}/images/og-image.png`; + + return { + title: `${title}`, + description, + openGraph: { + title, + description, + url: `${meta.baseURL}/docs/${pathName}`, + type: "article", + images: [ + { + url: ogImage, + width: 1200, + height: 630, + alt: title, + }, + ], + }, + twitter: { + card: "summary_large_image", + title, + description, + images: [ogImage], + }, + }; +} + +export default async function DocsPage({ params: { slug = [] } }: PageProps) { + const pathName = slug.join("/"); + const res = await getDocsForSlug(pathName); + + if (!res) notFound(); + + const { title, description, image, date } = res.frontmatter; + + // File path for edit link + const filePath = `contents/docs/${slug.join("/") || ""}/index.mdx`; + + const tocs = await getDocsTocs(pathName); + + return ( +
+
+ +
+ +
+ +

{title}

+

{description}

+
{res.content}
+
+ {date && ( +

+ Published on {formatDate2(date)} +

+ )} + +
+ +
+ +
+ +
+ ); +} diff --git a/app/docs/layout.tsx b/app/docs/layout.tsx new file mode 100644 index 0000000..ef73ca4 --- /dev/null +++ b/app/docs/layout.tsx @@ -0,0 +1,14 @@ +import { Leftbar } from "@/components/leftbar"; + +export default function DocsLayout({ + children, +}: Readonly<{ + children: React.ReactNode; +}>) { + return ( +
+ +
{children}
+
+ ); +} diff --git a/app/error.tsx b/app/error.tsx new file mode 100644 index 0000000..8a8ae0b --- /dev/null +++ b/app/error.tsx @@ -0,0 +1,44 @@ +"use client"; // Error components must be Client Components + +import { Button, buttonVariants } from "@/components/ui/button"; +import Link from "next/link"; +import { useEffect } from "react"; + +export default function Error({ + error, + reset, +}: { + error: Error & { digest?: string }; + reset: () => void; +}) { + useEffect(() => { + console.error(error); + }, [error]); + + return ( +
+
+

Oops!

+

+ Something went wrong {":`("} +

+

+ We're sorry, but an error occurred while processing your request. +

+
+
+ + + Back to homepage + +
+
+ ); +} diff --git a/app/layout.tsx b/app/layout.tsx new file mode 100644 index 0000000..2eb4c75 --- /dev/null +++ b/app/layout.tsx @@ -0,0 +1,96 @@ +import type { Metadata } from "next"; +import { ThemeProvider } from "@/components/contexts/theme-provider"; +import { Navbar } from "@/components/navbar"; +import { GeistSans } from "geist/font/sans"; +import { GeistMono } from "geist/font/mono"; +import { Footer } from "@/components/footer"; +import docuConfig from "@/docu.json"; +import { Toaster } from "@/components/ui/sonner"; +import "@/styles/globals.css"; + +const { meta } = docuConfig; + +// Default Metadata +const defaultMetadata: Metadata = { + metadataBase: new URL(meta.baseURL), + description: meta.description, + title: meta.title, + icons: { + icon: meta.favicon, + }, + openGraph: { + title: meta.title, + description: meta.description, + images: [ + { + url: new URL("/images/og-image.png", meta.baseURL).toString(), + width: 1200, + height: 630, + alt: String(meta.title), + }, + ], + locale: "en_US", + type: "website", + }, +}; + +// Dynamic Metadata Getter +export function getMetadata({ + title, + description, + image, +}: { + title?: string; + description?: string; + image?: string; +}): Metadata { + const ogImage = image ? new URL(`/images/${image}`, meta.baseURL).toString() : undefined; + + return { + ...defaultMetadata, + title: title ? `${title}` : defaultMetadata.title, + description: description || defaultMetadata.description, + openGraph: { + ...defaultMetadata.openGraph, + title: title || defaultMetadata.openGraph?.title, + description: description || defaultMetadata.openGraph?.description, + images: ogImage ? [ + { + url: ogImage, + width: 1200, + height: 630, + alt: String(title || defaultMetadata.openGraph?.title), + }, + ] : defaultMetadata.openGraph?.images, + }, + }; +} + +export default function RootLayout({ + children, +}: Readonly<{ + children: React.ReactNode; +}>) { + return ( + + + + +
+ {children} +
+