From 1adc104f4249b8ccf7e5c1b1495d766e0c3661f9 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 8 Oct 2025 09:58:57 +0530 Subject: [PATCH 1/2] Added Advance guide doc --- docs/advanced/architecture.mdx | 102 ++++++++++++ docs/advanced/client.mdx | 197 +++++++++++++++++++++++ docs/advanced/index.mdx | 26 +++ docs/advanced/plugins.mdx | 141 ++++++++++++++++ docs/advanced/routing.mdx | 239 ++++++++++++++++++++++++++++ docs/advanced/ssg.mdx | 182 +++++++++++++++++++++ package-lock.json | 16 ++ package.json | 1 + sidebars.js | 13 ++ src/theme/DocItem/styles.module.css | 2 +- static/img/architecture.png | Bin 0 -> 72918 bytes static/static-page.html | 100 ++++++++++++ 12 files changed, 1018 insertions(+), 1 deletion(-) create mode 100644 docs/advanced/architecture.mdx create mode 100644 docs/advanced/client.mdx create mode 100644 docs/advanced/index.mdx create mode 100644 docs/advanced/plugins.mdx create mode 100644 docs/advanced/routing.mdx create mode 100644 docs/advanced/ssg.mdx create mode 100644 static/img/architecture.png create mode 100644 static/static-page.html diff --git a/docs/advanced/architecture.mdx b/docs/advanced/architecture.mdx new file mode 100644 index 000000000..e79f0babc --- /dev/null +++ b/docs/advanced/architecture.mdx @@ -0,0 +1,102 @@ +--- +title: Architecture +description: "How CodeHarborHub’s documentation engine and architecture work together to build your site" +--- + +```mdx-code-block +import Zoom from 'react-medium-image-zoom'; +import 'react-medium-image-zoom/dist/styles.css'; +``` + + + +![Architecture overview](/img/architecture.png) + + + +This diagram explains how **CodeHarborHub’s documentation system** (powered by Docusaurus) works under the hood to build and serve your learning platform. Each **plugin** is responsible for collecting and processing content (like docs, tutorials, or blogs) and emitting structured JSON data. + +The **themes** provide the layout and UI components that transform this JSON data into dynamic, interactive web pages. + +The **bundler** then takes care of packaging everything—building both the **server** and **client** bundles that power the entire site experience. + +--- + +## Key Architectural Layers + +### 1. Plugin Layer + +Plugins manage content and configuration. Each plugin runs entirely in **Node.js**, processing Markdown, MDX, and metadata into structured JSON. + +For example: +- The **Docs Plugin** gathers all your course and guide files. +- The **Blog Plugin** handles educational blog content. +- The **Pages Plugin** renders custom pages like `/about`, `/events`, or `/community`. + +All plugin lifecycle methods run in **Node**. That means plugin code must be written in **CommonJS** (using `require`) or **ES Modules** (using `import/export`) that Node can execute. + +--- + +### 2. Theme Layer + +Themes define how the content looks and feels. Theme components are written in **React**, built with **Webpack**, and rendered on the client side. + +They receive the JSON output from plugins and render them as complete pages— +such as documentation layouts, course cards, contributor profiles, and interactive learning modules. + +**Themes and plugins don’t directly import or depend on each other.** +They communicate through **JSON data** and **route configuration**, ensuring modularity and scalability. + +A useful way to think about it: +> Imagine plugins are written in another language (like Rust or Go) — they just output structured data. +> The theme is the visual layer that interprets and displays that data beautifully. + +--- + +### 3. Configuration Layer + +Your `docusaurus.config.js` (or `docusaurus.config.mjs`) connects everything. + +It runs in **Node.js** and defines: +- Global settings like `title`, `url`, `baseUrl`, and `favicon` +- Plugin and theme configurations +- Site metadata, SEO tags, and integration settings + +You can pass callbacks or dynamic logic to plugins here. +However, only **serializable values** (those that survive `JSON.stringify()`) make it to the client. + +This means: +- ✅ Strings, numbers, arrays, and objects are preserved +- ⚠️ Functions, regexes, and complex data structures are lost in the browser bundle + +During bundling, the configuration file is serialized and injected into the client bundle, allowing the site to access global data via: + +```js +import { useDocusaurusContext } from '@docusaurus/core'; + +const { siteConfig } = useDocusaurusContext(); +console.log(siteConfig.themeConfig); +``` + +--- + +## Summary of the Build Process + +| Stage | Environment | Responsibility | +|--------|--------------|----------------| +| **Plugins** | Node.js | Collect content and generate JSON data | +| **Themes** | Browser + Webpack | Render JSON data into UI components | +| **Bundler** | Build (Webpack/Vite) | Output optimized server and client bundles | +| **Config** | Node.js | Define site structure and plugin options | + +--- + +## Why This Matters for CodeHarborHub + +This architecture allows CodeHarborHub to be: +- ⚡ **Fast and modular** — each content type (Docs, Blogs, Events) acts independently +- 🧠 **Extensible** — easily add new learning modules or plugins +- 🌐 **Universal** — supports versioning, localization, and custom themes +- 🔒 **Safe and scalable** — clean separation between content, configuration, and rendering + +--- \ No newline at end of file diff --git a/docs/advanced/client.mdx b/docs/advanced/client.mdx new file mode 100644 index 000000000..193bc2e5e --- /dev/null +++ b/docs/advanced/client.mdx @@ -0,0 +1,197 @@ +--- +title: Client Architecture +description: Understanding how the CodeHarborHub client system works +--- + +The **client architecture** of CodeHarborHub (built on Docusaurus) defines how the front-end interacts with React components, themes, and client-side modules. It focuses on modularity, performance, and extensibility — allowing you to customize your learning platform’s UI and logic. + +--- + +## Theme Aliases {#theme-aliases} + +Themes in CodeHarborHub work by exporting a set of **React components** such as `Navbar`, `Layout`, and `Footer`. These components render structured data provided by plugins. + +They are imported using the Webpack alias `@theme`: + +```js +import Navbar from '@theme/Navbar'; +``` + +### How it works + +The `@theme` alias points to several possible directories in this order of priority: + +1. `website/src/theme` — The **user’s custom theme directory** (highest priority). +2. `node_modules/@docusaurus/theme-*` — Theme package components. +3. Core fallback components provided by Docusaurus (least used). + +This creates a **layered architecture** — higher layers override lower ones. +For example: + +``` +website +├── node_modules +│ └── @docusaurus/theme-classic +│ └── theme +│ └── Navbar.js +└── src + └── theme + └── Navbar.js +``` + +Here, `website/src/theme/Navbar.js` takes precedence whenever you import `@theme/Navbar`. This concept is known as **swizzling** — overriding or extending existing components. + +### Wrapping and Extending Components + +If you want to extend a theme component instead of replacing it, use: + +- `@theme-original` — Imports the next component down the stack. +- `@theme-init` — Imports the base implementation from the original theme. + +Example: enhancing a `CodeBlock` component with a live playground: + +```js +import InitialCodeBlock from '@theme-init/CodeBlock'; +import React from 'react'; +import ReactLivePlayground from '@theme/ReactLivePlayground'; + +export default function CodeBlock(props) { + return props.live ? ( + + ) : ( + + ); +} +``` + +:::warning +Unless you’re building a reusable theme (like `@docusaurus/theme-live-codeblock`), you won’t usually need `@theme-init`. +::: + +### Visualization of Theme Stack + +Internally, CodeHarborHub loads components as a “stack” of layers: + +```text ++-------------------------------------------------+ +| website/src/theme/CodeBlock.js | <-- @theme/CodeBlock ++-------------------------------------------------+ +| theme-live-codeblock/theme/CodeBlock/index.js | <-- @theme-original/CodeBlock ++-------------------------------------------------+ +| plugin-awesome-codeblock/theme/CodeBlock.js | ++-------------------------------------------------+ +| theme-classic/theme/CodeBlock/index.js | <-- @theme-init/CodeBlock ++-------------------------------------------------+ +``` + +The **site layer** (`src/theme`) always takes precedence since it’s loaded last. + +--- + +## Client Modules {#client-modules} + +Client modules are **global scripts or styles** that run before React renders your site. They include JS and CSS that modify global state, register event listeners, or add global styling. + +Under the hood: + +```js title="@docusaurus/core/App.tsx" +import '@generated/client-modules'; +``` + +### Declaring Client Modules + +Plugins and sites can declare client modules using: + +- [`getClientModules`](https://docusaurus.io/docs/api/plugin-methods/lifecycle-apis#getClientModules) +- [`siteConfig.clientModules`](https://docusaurus.io/docs/api/docusaurus-config#clientModules) + +These modules are imported globally and executed both during server-side rendering (SSR) and client-side hydration. + +Example of a client-side script: + +```js title="mySiteGlobalJs.js" +import ExecutionEnvironment from '@docusaurus/ExecutionEnvironment'; + +if (ExecutionEnvironment.canUseDOM) { + window.addEventListener('keydown', (e) => { + if (e.code === 'Period') { + location.assign(location.href.replace('.com', '.dev')); + } + }); +} +``` + +Example of global CSS: + +```css title="mySiteGlobalCss.css" +/* Global stylesheet */ +.globalSelector { + color: #007bff; + font-weight: bold; +} +``` + +--- + +## Client Module Lifecycles {#client-module-lifecycles} + +Client modules can define **lifecycle functions** to handle route transitions in your single-page app (SPA). + +### Available Lifecycle Methods + +- `onRouteUpdate`: triggered when navigation starts +- `onRouteDidUpdate`: triggered after the new route has rendered + +These functions receive `{ location, previousLocation }` as parameters. + +Example: + +```js title="myClientModule.js" +export function onRouteDidUpdate({location, previousLocation}) { + if (location.pathname !== previousLocation?.pathname) { + const title = document.querySelector('h1'); + if (title) title.innerText += ' 🚀'; + } +} + +export function onRouteUpdate({location, previousLocation}) { + if (location.pathname !== previousLocation?.pathname) { + const progress = setTimeout(() => { + nprogress.start(); + }, 200); + return () => clearTimeout(progress); + } +} +``` + +TypeScript version: + +```ts title="myClientModule.ts" +import type {ClientModule} from '@docusaurus/types'; + +const module: ClientModule = { + onRouteUpdate({location, previousLocation}) { + // Custom navigation logic + }, + onRouteDidUpdate({location, previousLocation}) { + // DOM manipulations or analytics + }, +}; + +export default module; +``` + +Both lifecycles run on the **client side only** and are safe for accessing browser globals. + +--- + +:::tip Prefer React-based Implementations + +If your feature depends on **state**, **hooks**, or **context**, +it’s better to use [component swizzling](https://docusaurus.io/docs/swizzling#wrapping) instead of client modules. +Client modules are ideal for simple global effects, not for complex UI logic. +::: + +--- + +By understanding **theme aliases** and **client modules**, you can fully control CodeHarborHub’s front-end architecture — blending flexibility, modular design, and smooth client-side experiences. \ No newline at end of file diff --git a/docs/advanced/index.mdx b/docs/advanced/index.mdx new file mode 100644 index 000000000..50ac018f2 --- /dev/null +++ b/docs/advanced/index.mdx @@ -0,0 +1,26 @@ +--- +title: Advanced Tutorials +--- + +Welcome to the **Advanced Tutorials** section of CodeHarborHub! +Here, we dive deeper into the architecture, performance optimization, and real-world integrations that power modern web applications. + +This section may not be as structured as the beginner guides, but it will cover advanced and practical topics including: + +- Advanced component architecture +- Plugin and theme development +- Performance and SEO optimization +- Deployment strategies +- Integrations with AI and backend services + +```mdx-code-block +import DocCardList from '@theme/DocCardList'; + + +``` + +We assume you’ve completed the fundamental guides and understand the basics — such as configuring plugins, writing React components, and structuring Docusaurus pages. + +These tutorials are designed for **plugin authors**, **core contributors**, and **advanced developers**, so you’ll occasionally see references to internal APIs or low-level architecture details. + +Don’t worry if everything doesn’t click right away — take your time, experiment, and explore! 🚀 \ No newline at end of file diff --git a/docs/advanced/plugins.mdx b/docs/advanced/plugins.mdx new file mode 100644 index 000000000..9b9b0cb28 --- /dev/null +++ b/docs/advanced/plugins.mdx @@ -0,0 +1,141 @@ +--- +title: Plugins +--- + +Plugins are the **building blocks** of features in a CodeHarborHub (Docusaurus) site. Each plugin manages a specific feature — such as rendering content, transforming data, or integrating external services. + +Plugins can work independently or be distributed as part of a **preset** (a bundle of plugins and themes). + +--- + +## Creating Plugins {#creating-plugins} + +A plugin in Docusaurus is simply a **function** that receives two parameters: `context` and `options`. It returns a **plugin instance object** (or a promise) that defines how it behaves across the site’s lifecycle. + +For deeper insights, check out the [Plugin Method Reference](https://docusaurus.io/docs/api/plugin-methods). + +### Function Definition {#function-definition} + +You can define a plugin directly inside your `docusaurus.config.js` file: + +```js title="docusaurus.config.js" +export default { + // ... + plugins: [ + // highlight-start + async function myPlugin(context, options) { + return { + name: 'my-plugin', + async loadContent() { + // Load or generate data here + }, + async contentLoaded({content, actions}) { + // Use the data and add routes + }, + // Other lifecycle APIs + }; + }, + // highlight-end + ], +}; +``` + +### Module Definition {#module-definition} + +You can also define your plugin as a separate file or npm package: + +```js title="docusaurus.config.js" +export default { + // ... + plugins: [ + // Without options: + './my-plugin', + // Or with options: + ['./my-plugin', options], + ], +}; +``` + +Then, create a plugin module like this: + +```js title="my-plugin/index.js" +export default async function myPlugin(context, options) { + return { + name: 'my-plugin', + async loadContent() { + // Fetch or prepare plugin data + }, + async contentLoaded({content, actions}) { + // Connect content with routes or components + }, + }; +} +``` + +--- + +## Types of Plugins {#plugin-types} + +Plugins come in several types: + +- **Package:** Installed from npm (e.g., `@docusaurus/plugin-content-docs`) +- **Project:** Created within your local project using a file path +- **Local:** Inline function definitions within your config file +- **Synthetic:** Internal “virtual” plugins created by Docusaurus to support modular architecture + +You can see all installed plugins via the [Debug Metadata Panel](/__docusaurus/debug/metadata). + +--- + +## Plugin Design {#plugin-design} + +The plugin system in Docusaurus provides **hooks** into the site’s lifecycle — enabling you to: + +- Extend Webpack configurations +- Modify or load additional content +- Generate custom routes +- Create reusable UI components + +This design gives developers full control over both data flow and front-end rendering. + +--- + +## Theme Design {#theme-design} + +Once plugins load their content, the data is sent to the client side via: + +- [`createData` + `addRoute`](https://docusaurus.io/docs/api/plugin-methods/lifecycle-apis#addRoute) +- [`setGlobalData`](https://docusaurus.io/docs/api/plugin-methods/lifecycle-apis#setGlobalData) + +Since plugins and themes operate in **different environments** (Node vs. Browser), the data is **serialized** into plain JSON before being rendered. + +**Themes** provide the UI layer to visualize the plugin’s data. For instance, a blog system might include both a `plugin-content-blog` and a `theme-blog`. + +```js title="docusaurus.config.js" +export default { + themes: ['theme-blog'], + plugins: ['plugin-content-blog'], +}; +``` + +If you want to switch design styles, you can easily replace the theme: + +```js title="docusaurus.config.js" +export default { + themes: ['theme-blog-bootstrap'], + plugins: ['plugin-content-blog'], +}; +``` + +Even though both themes receive the same data, they can render it completely differently — allowing flexible, modular UI experiences. + +--- + +## Summary {#summary} + +- **Themes** share the same lifecycle methods as **Plugins**. +- Themes run **after** all plugins have loaded. +- Themes add UI component aliases through `getThemePath`. +- Plugins manage **data and logic**, while themes manage **presentation**. + +Together, plugins and themes form the **core modular architecture** of a Docusaurus-powered site like CodeHarborHub — allowing limitless customization, scalability, and innovation. \ No newline at end of file diff --git a/docs/advanced/routing.mdx b/docs/advanced/routing.mdx new file mode 100644 index 000000000..57d3b7106 --- /dev/null +++ b/docs/advanced/routing.mdx @@ -0,0 +1,239 @@ +--- +title: Advanced Routing +description: "Learn how Docusaurus handles routing across docs, blog, and pages. Understand route structure, path mapping, and SPA transitions." +sidebar_label: Routing +tags: [routing, docusaurus, react-router, docs, pages, blog] +--- + +```mdx-code-block +import Link from '@docusaurus/Link'; +import {useLatestVersion, useActiveDocContext} from '@docusaurus/plugin-content-docs/client'; +import {useLocation} from '@docusaurus/router'; +``` + +Docusaurus uses a **single-page application (SPA)** routing system — meaning every route corresponds to **one component**. + +In this guide, we’ll explore how Docusaurus manages routing for **Docs**, **Blog**, and **Pages**, and then dive deeper into how the routing system itself works behind the scenes. + +--- + +## Routing in Content Plugins {#routing-in-content-plugins} + +Each content plugin defines a `routeBasePath`, which tells Docusaurus **where to mount routes**. + +- **Docs plugin:** `/docs` by default +- **Blog plugin:** `/blog` +- **Pages plugin:** `/` + +Here’s how these routes connect in the URL hierarchy: + +```mermaid +graph LR; + A(["https://codeharborhub.github.io/"]) + B(["/base-url/"]) + C(["/docs/"]) + D(["/blog/"]) + E(["/"]) + F["Docs Routes"] + G["Blog Routes"] + H["Page Routes"] + A---B; + B---C; + B---D; + B---E; + C---F; + D---G; + E---H; +``` + +When a user visits `/docs/configuration`, Docusaurus finds the `/docs` branch, and then loads the corresponding document route. + +You can fully customize your route structure. For instance, setting `routeBasePath: '/'` in **Docs-only mode** removes the `/docs` prefix while keeping all other plugins intact. + +--- + +## Pages Routing {#pages-routing} + +**Pages** are the simplest form of routes — file paths directly map to URLs. +For example: + +``` +src/pages/about.mdx → /about +src/pages/index.js → / +``` + +- Markdown pages render using `@theme/MDXPage`. +- React components render directly as route components. + +See [Creating Pages](../guides/creating-pages.mdx#routing) for more details. + +--- + +## Blog Routing {#blog-routing} + +The blog plugin auto-generates several types of routes: + +| Route Type | Example URL | Customizable Option | Component | +| ------------------- | ----------------------------- | ------------------- | -------------------------- | +| **Posts List** | `/`, `/page/2`, `/page/3` | `pageBasePath` | `@theme/BlogListPage` | +| **Individual Post** | `/2025/10/08/launch-post` | `slug` front matter | `@theme/BlogPostPage` | +| **Tags List** | `/tags` | `tagsBasePath` | `@theme/BlogTagsListPage` | +| **Tag Pages** | `/tags/education`, `/tags/ai` | `permalink` in tag | `@theme/BlogTagsPostsPage` | +| **Archive Page** | `/archive` | `archiveBasePath` | `@theme/BlogArchivePage` | + +Each route is generated automatically, but you can override any path with custom front matter. + +--- + +## Docs Routing {#docs-routing} + +Docs routing is **hierarchical** and **versioned**. Each version has its own route tree, sidebar, and context. + +For example: + +``` +/docs/ → Current version +/docs/next → Next version +/docs/1.0.0 → Past version +``` + +This allows seamless version switching while preserving sidebar state. + +```mdx-code-block +export const URLPath = () => {useLocation().pathname}; +export const FilePath = () => { + const currentVersion = useActiveDocContext('default').activeVersion.name; + return {currentVersion === 'current' ? './docs/' : `./versioned_docs/version-${currentVersion}/`}advanced/routing.md; +}; +``` + +This page, , is generated from . The doc content is displayed inside `@theme/DocPage`, which manages layout, sidebar, and navigation. + +--- + +## File Paths vs URL Paths {#file-paths-and-url-paths} + +In Docusaurus, **file paths map to URL paths**, unless overridden using the `slug` front matter. + +### Example Mapping + +| File Path | URL Path | +| ------------------------------ | ------------------------- | +| `./docs/advanced/routing.md` | `/docs/advanced/routing` | +| `./blog/2025-10-08-launch.mdx` | `/blog/2025/10/08/launch` | + +### Rules for Markdown Links + +- `@site` prefix → Asset file path +- `http(s)://` prefix → External URL +- No extension → URL path +- `.md(x)` extension → Converts file path to URL +- Other extensions → Treated as [assets](../guides/markdown-features/markdown-features-assets.mdx) + +--- + +## Routes Become HTML Files {#routes-become-html-files} + +Every route in Docusaurus compiles into a **static HTML file** during build. For instance, the route `/docs/advanced/routing` maps to: + +``` +/build/docs/advanced/routing/index.html +``` + +If `trailingSlash` is disabled, the same route becomes `routing.html`. + +This allows hosting on any static server (like GitHub Pages or Vercel) — Docusaurus handles **server-side rendering → static HTML conversion** automatically. + +### Example + +```bash +build/ +├── docs/ +│ └── advanced/ +│ └── routing/ +│ └── index.html # /docs/advanced/routing +└── index.html # / +``` + +When using a custom `baseUrl`, ensure assets resolve correctly (e.g., `/base/assets/js/...`). + +--- + +## Generating and Accessing Routes {#generating-and-accessing-routes} + +Use the `addRoute` lifecycle method to programmatically add routes: + +```js title="plugin-example.js" +actions.addRoute({ + path: "/custom", + component: "@site/src/pages/CustomPage.js", +}); +``` + +All routes are aggregated in `.docusaurus/routes.js`. +You can inspect them in the [Debug Routes Panel](/__docusaurus/debug/routes). + +### Accessing Routes in React + +You can access route data using `@docusaurus/router`, a wrapper around React Router. + +```jsx title="RouteInfo.js" +import React from "react"; +import { useLocation } from "@docusaurus/router"; + +export function PageRoute() { + const location = useLocation(); + return ( + + You are currently on {location.pathname} + + ); +} +``` + +```mdx-code-block + + + You are currently on {location.pathname} + + +``` + +--- + +## Escaping SPA Redirects {#escaping-from-spa-redirects} + +Because Docusaurus is an SPA, it handles navigation through React Router. However, if you link to static HTML files that aren’t part of Docusaurus routes, use the special `pathname://` protocol to perform a **non-SPA redirect**. + +```md +- [pathname:///static-page](pathname:///static-page) +``` + + + +- [`pathname:///static-page`](pathname:///static-page) + + + +This ensures Docusaurus doesn’t attempt to render missing routes or show a 404 page. + +You can also use `pathname://` for static assets: + +```md title="my-doc.md" +![Static image](pathname:///img/codeharborhub-banner.png) + +[Download PDF](pathname:///files/tutorial.pdf) +``` + +--- + +## Summary + +- Docusaurus follows a **SPA routing system** built on React Router. +- Every content plugin defines its **route base path**. +- **Docs** support **nested and versioned** routes. +- URLs map directly from files but can be customized using `slug`. +- During build, routes become **static HTML files** for deployment. +- Use `pathname://` for non-SPA links or static assets. + +With this routing power, our **CodeHarborHub** site can scale efficiently — from a simple landing page to a complex multi-version documentation ecosystem. \ No newline at end of file diff --git a/docs/advanced/ssg.mdx b/docs/advanced/ssg.mdx new file mode 100644 index 000000000..1f9991dfb --- /dev/null +++ b/docs/advanced/ssg.mdx @@ -0,0 +1,182 @@ +--- +title: "Static Site Generation (SSG)" +sidebar_label: Static Site Generation +description: Learn how CodeHarborHub builds blazing-fast static sites using React and Docusaurus for better performance and SEO. +--- + +In our [architecture](architecture.mdx) guide, we explained how the theme and plugins interact during build time. Now, let’s dive deeper into **Static Site Generation (SSG)** — the process that powers CodeHarborHub’s speed and SEO optimization. + +Docusaurus, which powers our site, **statically renders React components into HTML**, allowing the content to load instantly and rank better on search engines. + +--- + +## How It Works + +The theme is compiled **twice** during the build: + +- **Server-side rendering (SSR)**: Compiles React in a virtual environment using [React DOM Server](https://reactjs.org/docs/react-dom-server.html). + This process outputs static HTML files — no browser APIs like `window` or `document` exist here. +- **Client-side rendering (CSR)**: Runs React inside the browser, allowing dynamic features such as animations, interactivity, and data updates. + +:::info SSR or SSG? +Although _server-side rendering (SSR)_ and _static site generation (SSG)_ can differ, Docusaurus primarily performs **SSG** — meaning everything is rendered once during build time, then served statically via CDN for lightning-fast delivery. + +Unlike frameworks like [Next.js](https://nextjs.org/), CodeHarborHub doesn’t re-render content per request. Instead, it delivers optimized, pre-rendered pages directly. +::: + +--- + +## Common SSR Pitfalls + +You might already know that Node globals like `process` or `'fs'` aren’t available in the browser but it’s equally important to remember that **browser globals like `window` or `document` aren’t available during SSR**. + +```jsx +import React from 'react'; + +export default function WhereAmI() { + return {window.location.href}; +} +``` + +Running this code during `docusaurus build` will trigger: + +``` +ReferenceError: window is not defined +``` + +**Why?** + +Because the site is rendered on the server — where no `window` object exists. + +--- + +## The Exception: `process.env.NODE_ENV` + +```mdx-code-block +
+What about process.env.NODE_ENV? +``` + +You can safely use `process.env.NODE_ENV` because Webpack injects it during build time. +This is useful for conditional rendering or optimizing development vs production builds. + +```jsx +import React from 'react'; + +export default function ExpensiveComponent() { + if (process.env.NODE_ENV === 'development') { + return <>Development Mode: Skipping heavy operations; + } + const result = someExpensiveOperation(); + return <>{result}; +} +``` + +```mdx-code-block +
+``` + +--- + +## Understanding SSR in Depth + +React isn’t just for interactivity — it’s also a **templating engine**. + +Docusaurus leverages this to **render your React components into pure HTML**, which is instantly visible when a page loads. Afterward, the JavaScript bundle hydrates the page — turning it into a dynamic single-page app. + +This two-step process ensures: +- 🚀 **Faster perceived load times** +- 🌐 **SEO-optimized content** +- 🧠 **Progressive enhancement** (works even before JS fully loads) + +--- + +## Escape Hatches: When You Need Browser APIs + +Sometimes, you’ll need to access browser-only functionality. +For example: +- Running code blocks in real time +- Loading user themes dynamically +- Displaying data fetched from APIs + +Here are safe ways to handle this: + +### 1. `` + +Wrap browser-specific components inside [``](https://docusaurus.io/docs/docusaurus-core#browseronly): + +```jsx +import BrowserOnly from '@docusaurus/BrowserOnly'; + +function MyBrowserComponent() { + return ( + Loading...}> + {() => { + const BrowserLib = require('browser-lib').BrowserLib; + return ; + }} + + ); +} +``` + +✅ Ensures the component runs only in the browser — never during static rendering. + +--- + +### 2. `useIsBrowser()` + +Use this hook to conditionally run logic depending on the environment: + +```jsx +import useIsBrowser from '@docusaurus/useIsBrowser'; + +function MyComponent() { + const isBrowser = useIsBrowser(); + const currentURL = isBrowser ? window.location.href : 'Loading...'; + return {currentURL}; +} +``` + +--- + +### 3. `useEffect()` + +Move browser-only side effects inside `useEffect()` so they execute only after hydration: + +```jsx +import React, { useEffect } from 'react'; + +function MyComponent() { + useEffect(() => { + console.log("Now running in browser!"); + }, []); + return Welcome to CodeHarborHub!; +} +``` + +--- + +### 4. `ExecutionEnvironment` + +For quick checks, you can use the `ExecutionEnvironment` utility: + +```js title="a-client-module.js" +import ExecutionEnvironment from '@docusaurus/ExecutionEnvironment'; + +if (ExecutionEnvironment.canUseDOM) { + document.title = "Loaded on client!"; +} +``` + +--- + +## Summary + +- 🧱 CodeHarborHub statically builds your pages using **SSG** for speed and SEO. +- ⚙️ React components are rendered on the server first (SSR) and hydrated later (CSR). +- 🧩 Use safe methods like ``, `useIsBrowser()`, or `useEffect()` when accessing browser APIs. +- 🚫 Avoid using `window` or `document` directly during build time. + +With these principles, you can confidently create interactive yet highly optimized static pages — +the foundation of what makes **CodeHarborHub** fast, scalable, and developer-friendly ⚡ \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index c508c4261..3014c206a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -55,6 +55,7 @@ "react-dom": "^18.0.0", "react-icons": "^5.2.1", "react-lite-youtube-embed": "^2.4.0", + "react-medium-image-zoom": "^5.4.0", "react-phone-input-2": "^2.15.1", "react-popper": "^2.3.0", "react-redux": "^9.1.0", @@ -22801,6 +22802,21 @@ "webpack": ">=4.41.1 || 5.x" } }, + "node_modules/react-medium-image-zoom": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/react-medium-image-zoom/-/react-medium-image-zoom-5.4.0.tgz", + "integrity": "sha512-BsE+EnFVQzFIlyuuQrZ9iTwyKpKkqdFZV1ImEQN573QPqGrIUuNni7aF+sZwDcxlsuOMayCr6oO/PZR/yJnbRg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/rpearce" + } + ], + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, "node_modules/react-phone-input-2": { "version": "2.15.1", "resolved": "https://registry.npmjs.org/react-phone-input-2/-/react-phone-input-2-2.15.1.tgz", diff --git a/package.json b/package.json index 54cb8a484..4145c8618 100644 --- a/package.json +++ b/package.json @@ -62,6 +62,7 @@ "react-dom": "^18.0.0", "react-icons": "^5.2.1", "react-lite-youtube-embed": "^2.4.0", + "react-medium-image-zoom": "^5.4.0", "react-phone-input-2": "^2.15.1", "react-popper": "^2.3.0", "react-redux": "^9.1.0", diff --git a/sidebars.js b/sidebars.js index 367c6aff9..a114a76d4 100644 --- a/sidebars.js +++ b/sidebars.js @@ -85,6 +85,19 @@ const sidebars = { "seo", ], }, + + { + type: "category", + label: "Advanced Guides", + link: { type: "doc", id: "advanced/index" }, + items: [ + "advanced/architecture", + 'advanced/plugins', + 'advanced/routing', + 'advanced/ssg', + 'advanced/client', + ], + }, ], }; diff --git a/src/theme/DocItem/styles.module.css b/src/theme/DocItem/styles.module.css index 1964309c5..94ebcdf83 100644 --- a/src/theme/DocItem/styles.module.css +++ b/src/theme/DocItem/styles.module.css @@ -68,7 +68,7 @@ } .docsRating { - max-width: 600px; + /* max-width: 600px; */ text-align: center; font-family: var(--ifm-font-family-base); } diff --git a/static/img/architecture.png b/static/img/architecture.png new file mode 100644 index 0000000000000000000000000000000000000000..8896e7567354ecd4a1af1d0d48dfd2d183ecafd8 GIT binary patch literal 72918 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 + + + + From 96fca0603277bd69c9f92238beb5ff6437933fe8 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 8 Oct 2025 18:09:34 +0530 Subject: [PATCH 2/2] try to fix bug --- docs/advanced/routing.mdx | 235 +------------------------------------- 1 file changed, 1 insertion(+), 234 deletions(-) diff --git a/docs/advanced/routing.mdx b/docs/advanced/routing.mdx index 57d3b7106..05a45c989 100644 --- a/docs/advanced/routing.mdx +++ b/docs/advanced/routing.mdx @@ -3,237 +3,4 @@ title: Advanced Routing description: "Learn how Docusaurus handles routing across docs, blog, and pages. Understand route structure, path mapping, and SPA transitions." sidebar_label: Routing tags: [routing, docusaurus, react-router, docs, pages, blog] ---- - -```mdx-code-block -import Link from '@docusaurus/Link'; -import {useLatestVersion, useActiveDocContext} from '@docusaurus/plugin-content-docs/client'; -import {useLocation} from '@docusaurus/router'; -``` - -Docusaurus uses a **single-page application (SPA)** routing system — meaning every route corresponds to **one component**. - -In this guide, we’ll explore how Docusaurus manages routing for **Docs**, **Blog**, and **Pages**, and then dive deeper into how the routing system itself works behind the scenes. - ---- - -## Routing in Content Plugins {#routing-in-content-plugins} - -Each content plugin defines a `routeBasePath`, which tells Docusaurus **where to mount routes**. - -- **Docs plugin:** `/docs` by default -- **Blog plugin:** `/blog` -- **Pages plugin:** `/` - -Here’s how these routes connect in the URL hierarchy: - -```mermaid -graph LR; - A(["https://codeharborhub.github.io/"]) - B(["/base-url/"]) - C(["/docs/"]) - D(["/blog/"]) - E(["/"]) - F["Docs Routes"] - G["Blog Routes"] - H["Page Routes"] - A---B; - B---C; - B---D; - B---E; - C---F; - D---G; - E---H; -``` - -When a user visits `/docs/configuration`, Docusaurus finds the `/docs` branch, and then loads the corresponding document route. - -You can fully customize your route structure. For instance, setting `routeBasePath: '/'` in **Docs-only mode** removes the `/docs` prefix while keeping all other plugins intact. - ---- - -## Pages Routing {#pages-routing} - -**Pages** are the simplest form of routes — file paths directly map to URLs. -For example: - -``` -src/pages/about.mdx → /about -src/pages/index.js → / -``` - -- Markdown pages render using `@theme/MDXPage`. -- React components render directly as route components. - -See [Creating Pages](../guides/creating-pages.mdx#routing) for more details. - ---- - -## Blog Routing {#blog-routing} - -The blog plugin auto-generates several types of routes: - -| Route Type | Example URL | Customizable Option | Component | -| ------------------- | ----------------------------- | ------------------- | -------------------------- | -| **Posts List** | `/`, `/page/2`, `/page/3` | `pageBasePath` | `@theme/BlogListPage` | -| **Individual Post** | `/2025/10/08/launch-post` | `slug` front matter | `@theme/BlogPostPage` | -| **Tags List** | `/tags` | `tagsBasePath` | `@theme/BlogTagsListPage` | -| **Tag Pages** | `/tags/education`, `/tags/ai` | `permalink` in tag | `@theme/BlogTagsPostsPage` | -| **Archive Page** | `/archive` | `archiveBasePath` | `@theme/BlogArchivePage` | - -Each route is generated automatically, but you can override any path with custom front matter. - ---- - -## Docs Routing {#docs-routing} - -Docs routing is **hierarchical** and **versioned**. Each version has its own route tree, sidebar, and context. - -For example: - -``` -/docs/ → Current version -/docs/next → Next version -/docs/1.0.0 → Past version -``` - -This allows seamless version switching while preserving sidebar state. - -```mdx-code-block -export const URLPath = () => {useLocation().pathname}; -export const FilePath = () => { - const currentVersion = useActiveDocContext('default').activeVersion.name; - return {currentVersion === 'current' ? './docs/' : `./versioned_docs/version-${currentVersion}/`}advanced/routing.md; -}; -``` - -This page, , is generated from . The doc content is displayed inside `@theme/DocPage`, which manages layout, sidebar, and navigation. - ---- - -## File Paths vs URL Paths {#file-paths-and-url-paths} - -In Docusaurus, **file paths map to URL paths**, unless overridden using the `slug` front matter. - -### Example Mapping - -| File Path | URL Path | -| ------------------------------ | ------------------------- | -| `./docs/advanced/routing.md` | `/docs/advanced/routing` | -| `./blog/2025-10-08-launch.mdx` | `/blog/2025/10/08/launch` | - -### Rules for Markdown Links - -- `@site` prefix → Asset file path -- `http(s)://` prefix → External URL -- No extension → URL path -- `.md(x)` extension → Converts file path to URL -- Other extensions → Treated as [assets](../guides/markdown-features/markdown-features-assets.mdx) - ---- - -## Routes Become HTML Files {#routes-become-html-files} - -Every route in Docusaurus compiles into a **static HTML file** during build. For instance, the route `/docs/advanced/routing` maps to: - -``` -/build/docs/advanced/routing/index.html -``` - -If `trailingSlash` is disabled, the same route becomes `routing.html`. - -This allows hosting on any static server (like GitHub Pages or Vercel) — Docusaurus handles **server-side rendering → static HTML conversion** automatically. - -### Example - -```bash -build/ -├── docs/ -│ └── advanced/ -│ └── routing/ -│ └── index.html # /docs/advanced/routing -└── index.html # / -``` - -When using a custom `baseUrl`, ensure assets resolve correctly (e.g., `/base/assets/js/...`). - ---- - -## Generating and Accessing Routes {#generating-and-accessing-routes} - -Use the `addRoute` lifecycle method to programmatically add routes: - -```js title="plugin-example.js" -actions.addRoute({ - path: "/custom", - component: "@site/src/pages/CustomPage.js", -}); -``` - -All routes are aggregated in `.docusaurus/routes.js`. -You can inspect them in the [Debug Routes Panel](/__docusaurus/debug/routes). - -### Accessing Routes in React - -You can access route data using `@docusaurus/router`, a wrapper around React Router. - -```jsx title="RouteInfo.js" -import React from "react"; -import { useLocation } from "@docusaurus/router"; - -export function PageRoute() { - const location = useLocation(); - return ( - - You are currently on {location.pathname} - - ); -} -``` - -```mdx-code-block - - - You are currently on {location.pathname} - - -``` - ---- - -## Escaping SPA Redirects {#escaping-from-spa-redirects} - -Because Docusaurus is an SPA, it handles navigation through React Router. However, if you link to static HTML files that aren’t part of Docusaurus routes, use the special `pathname://` protocol to perform a **non-SPA redirect**. - -```md -- [pathname:///static-page](pathname:///static-page) -``` - - - -- [`pathname:///static-page`](pathname:///static-page) - - - -This ensures Docusaurus doesn’t attempt to render missing routes or show a 404 page. - -You can also use `pathname://` for static assets: - -```md title="my-doc.md" -![Static image](pathname:///img/codeharborhub-banner.png) - -[Download PDF](pathname:///files/tutorial.pdf) -``` - ---- - -## Summary - -- Docusaurus follows a **SPA routing system** built on React Router. -- Every content plugin defines its **route base path**. -- **Docs** support **nested and versioned** routes. -- URLs map directly from files but can be customized using `slug`. -- During build, routes become **static HTML files** for deployment. -- Use `pathname://` for non-SPA links or static assets. - -With this routing power, our **CodeHarborHub** site can scale efficiently — from a simple landing page to a complex multi-version documentation ecosystem. \ No newline at end of file +--- \ No newline at end of file

_ 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 literal 0 HcmV?d00001 diff --git a/static/static-page.html b/static/static-page.html new file mode 100644 index 000000000..1a28d9665 --- /dev/null +++ b/static/static-page.html @@ -0,0 +1,100 @@ + + + + + + Static Page | CodeHarborHub + + + + + + +