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..05a45c989 --- /dev/null +++ b/docs/advanced/routing.mdx @@ -0,0 +1,6 @@ +--- +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] +--- \ 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 000000000..8896e7567 Binary files /dev/null and b/static/img/architecture.png differ 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 + + + + + + +
+

Static Page 🧩

+

+ This is a fully static HTML page that lives outside your Docusaurus app. + You can reach it using: +

+
pathname:///static-page
+

+ Use this approach for landing pages, legacy pages, or static files that + don’t need React rendering. +

+ ← Back to CodeHarborHub + +
+ © CodeHarborHub. Built with 💙 and + Docusaurus. +
+
+ + + +