Merge pull request 'docs/dev' (#20) from docs/dev into main
Reviewed-on: eigen/fe-monorepo-template#20
This commit is contained in:
@@ -33,8 +33,15 @@ This repository utilizes a monorepo architecture to seamlessly share core system
|
|||||||
|
|
||||||
* **View in Git Repository (Raw Markdown):** [Read Overview Documentation](apps/docs-dev/src/overview.md)
|
* **View in Git Repository (Raw Markdown):** [Read Overview Documentation](apps/docs-dev/src/overview.md)
|
||||||
* **Run Documentation Locally:**
|
* **Run Documentation Locally:**
|
||||||
|
|
||||||
|
If this is your first time running the documentation, ensure you install the dependencies first:
|
||||||
```bash
|
```bash
|
||||||
pnpm --filter docs-dev dev
|
pnpm install
|
||||||
|
```
|
||||||
|
|
||||||
|
Then, start the documentation server:
|
||||||
|
```bash
|
||||||
|
pnpm dev:docs-dev
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|||||||
@@ -10,6 +10,12 @@ const config = withMermaid(
|
|||||||
['link', { rel: 'icon', href: '/favicon.svg' }] // Jika Anda menggunakan favicon.svg
|
['link', { rel: 'icon', href: '/favicon.svg' }] // Jika Anda menggunakan favicon.svg
|
||||||
],
|
],
|
||||||
themeConfig: {
|
themeConfig: {
|
||||||
|
search: {
|
||||||
|
provider: 'local',
|
||||||
|
options: {
|
||||||
|
detailedView: true
|
||||||
|
}
|
||||||
|
},
|
||||||
logo: '/logo.svg',
|
logo: '/logo.svg',
|
||||||
nav: [
|
nav: [
|
||||||
{ text: 'Docs', link: '/overview' },
|
{ text: 'Docs', link: '/overview' },
|
||||||
|
|||||||
@@ -78,3 +78,39 @@
|
|||||||
width: 28px;
|
width: 28px;
|
||||||
margin-right: 0; /* Margin sudah digantikan oleh 'gap' pada parent */
|
margin-right: 0; /* Margin sudah digantikan oleh 'gap' pada parent */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ==========================================================================
|
||||||
|
ADJUSTING SEARCH BAR POSITION & SPACING
|
||||||
|
========================================================================== */
|
||||||
|
|
||||||
|
/* Menggeser Search agar lebih dekat ke Logo */
|
||||||
|
.VPNavBarSearch {
|
||||||
|
margin-left: 0px;
|
||||||
|
margin-right: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Memperbaiki tampilan tombol Search agar lebih kompak */
|
||||||
|
.VPNavBarSearch .DocSearch-Button {
|
||||||
|
border-radius: 8px;
|
||||||
|
height: 32px;
|
||||||
|
padding: 0 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Kustomisasi warna background & border (Light Mode) */
|
||||||
|
:not(.dark) .VPNavBarSearch .DocSearch-Button {
|
||||||
|
background-color: #f3f4f6;
|
||||||
|
border-color: #e5e7eb; /* Border abu-abu tipis untuk light mode */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Kustomisasi warna background & border (Dark Mode) */
|
||||||
|
.dark .VPNavBarSearch .DocSearch-Button {
|
||||||
|
background-color: var(--vp-c-bg-soft);
|
||||||
|
border-color: #374151; /* Border gelap yang elegan untuk dark mode */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Opsional: Jika ingin Search tetap di tengah namun punya batasan */
|
||||||
|
@media (min-width: 768px) {
|
||||||
|
.VPNavBar .VPNavBarSearch {
|
||||||
|
flex-grow: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,7 +1,11 @@
|
|||||||
|
|
||||||
# Desktop Auto-Update System
|
# Desktop Auto-Update System
|
||||||
|
|
||||||
`apps/desktop` utilizes a unified update lifecycle powered by **electron-updater**. This architecture ensures seamless, background delivery of application patches, maintaining version parity across our global user base.
|
> **Architectural Foundation:** [electron-updater](https://www.npmjs.com/package/electron-updater) · [electron-builder](https://www.electron.build/) · [GitHub Actions](https://docs.github.com/en/actions)
|
||||||
|
>
|
||||||
|
> **Description:** Comprehensive auto-update system documentation covering the reactive IPC update flow, GitHub/S3/generic release providers, CI/CD pipeline configuration, code signing requirements, and diagnostic runbook.
|
||||||
|
|
||||||
|
`apps/desktop` utilizes a unified update lifecycle powered by **[electron-updater](https://www.npmjs.com/package/electron-updater)**. This architecture ensures seamless, background delivery of application patches, maintaining version parity across our global user base.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -75,7 +79,7 @@ publish:
|
|||||||
|
|
||||||
### Operational Mechanics
|
### Operational Mechanics
|
||||||
|
|
||||||
1. When `electron-builder --publish always` executes, it:
|
1. When [`electron-builder`](https://www.electron.build/) `--publish always` executes, it:
|
||||||
|
|
||||||
- Compiles the application for the target platform.
|
- Compiles the application for the target platform.
|
||||||
- Uploads the installer(s) to a **GitHub Release** tagged with the version from `package.json`.
|
- Uploads the installer(s) to a **GitHub Release** tagged with the version from `package.json`.
|
||||||
@@ -178,9 +182,9 @@ jobs:
|
|||||||
|
|
||||||
## ☁️ Deployment Strategies
|
## ☁️ Deployment Strategies
|
||||||
|
|
||||||
### AWS S3 (Private Infrastructure)
|
### [AWS S3](https://aws.amazon.com/s3/) (Private Infrastructure)
|
||||||
|
|
||||||
For enterprise environments requiring private infrastructure, the system can be reconfigured to target an **AWS S3 Bucket** or a **CloudFront Distribution**.
|
For enterprise environments requiring private infrastructure, the system can be reconfigured to target an **[AWS S3](https://aws.amazon.com/s3/) Bucket** or a **CloudFront Distribution**.
|
||||||
|
|
||||||
Update `electron-builder.yml`:
|
Update `electron-builder.yml`:
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,10 @@
|
|||||||
|
|
||||||
# Desktop Configuration Guide
|
# Desktop Configuration Guide
|
||||||
|
|
||||||
|
> **Architectural Foundation:** [Electron Protocol API](https://www.electronjs.org/docs/latest/api/protocol) · [electron-builder](https://www.electron.build/) · [React Router](https://reactrouter.com/)
|
||||||
|
>
|
||||||
|
> **Description:** Runtime configuration guide for the Desktop Wrapper covering target app orchestration, deterministic path resolution, custom app:// protocol routing with SPA fallback, and the HashRouter disaster recovery procedure.
|
||||||
|
|
||||||
The Blueprint for Runtime Control.
|
The Blueprint for Runtime Control.
|
||||||
|
|
||||||
> This guide defines the operational parameters of the Desktop Wrapper. It governs the orchestration of target applications, encapsulates the mechanics of our proprietary production routing, and provides a fail-safe **Break Glass Procedure** for emergency infrastructure transitions.
|
> This guide defines the operational parameters of the Desktop Wrapper. It governs the orchestration of target applications, encapsulates the mechanics of our proprietary production routing, and provides a fail-safe **Break Glass Procedure** for emergency infrastructure transitions.
|
||||||
@@ -121,9 +125,9 @@ The following matrix defines how the target app's static assets are resolved acr
|
|||||||
|
|
||||||
### The Constraint
|
### The Constraint
|
||||||
|
|
||||||
React applications using `BrowserRouter` rely on a fundamental server-side contract: **every URL path must return `index.html`**. Paths like `/dashboard`, `/auth/login`, and `/settings/profile` do not correspond to physical files — they are virtual routes resolved entirely by the client-side router.
|
React applications using [`BrowserRouter`](https://reactrouter.com/) rely on a fundamental server-side contract: **every URL path must return `index.html`**. Paths like `/dashboard`, `/auth/login`, and `/settings/profile` do not correspond to physical files — they are virtual routes resolved entirely by the client-side router.
|
||||||
|
|
||||||
Electron's default `file://` protocol breaks this contract. Requesting `file:///app/dashboard` triggers a literal filesystem lookup for a file named `dashboard`, which does not exist, resulting in a blank screen or an OS-level "file not found" error.
|
[Electron](https://www.electronjs.org/)'s default `file://` protocol breaks this contract. Requesting `file:///app/dashboard` triggers a literal filesystem lookup for a file named `dashboard`, which does not exist, resulting in a blank screen or an OS-level "file not found" error.
|
||||||
|
|
||||||
### The Solution: A Privileged Virtual File System
|
### The Solution: A Privileged Virtual File System
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,13 @@ outline: [2, 3]
|
|||||||
|
|
||||||
# IPC Architecture & Security Model
|
# IPC Architecture & Security Model
|
||||||
|
|
||||||
> **Scope**: Electron Main ↔ Renderer process communication
|
> **Architectural Foundation:** [Electron contextBridge](https://www.electronjs.org/docs/latest/api/context-bridge) · [Electron ipcMain](https://www.electronjs.org/docs/latest/api/ipc-main) · [Electron ipcRenderer](https://www.electronjs.org/docs/latest/api/ipc-renderer)
|
||||||
|
>
|
||||||
|
> **Description:** Hardened IPC security model enforcing privilege separation via contextBridge, defining the Three-Step Bridge SOP for native feature exposure, the verified channel manifest, and critical anti-pattern audit checklist.
|
||||||
|
|
||||||
|
|
||||||
|
> **Scope**: [Electron](https://www.electronjs.org/) Main ↔ Renderer process communication
|
||||||
|
>
|
||||||
> **Enforcement Level**: Mandatory — deviations constitute security violations
|
> **Enforcement Level**: Mandatory — deviations constitute security violations
|
||||||
|
|
||||||
This document defines the **hardened security perimeter** and communication topology governing the Desktop Wrapper. Every native capability exposed to the Renderer is mediated through a **non-bypassable IPC bridge**, enforcing strict privilege separation between the Node.js Main Process and untrusted web content.
|
This document defines the **hardened security perimeter** and communication topology governing the Desktop Wrapper. Every native capability exposed to the Renderer is mediated through a **non-bypassable IPC bridge**, enforcing strict privilege separation between the Node.js Main Process and untrusted web content.
|
||||||
@@ -32,7 +38,7 @@ The architecture operates on three invariants:
|
|||||||
|
|
||||||
## Privilege Separation Model
|
## Privilege Separation Model
|
||||||
|
|
||||||
The desktop wrapper enforces a **strict privilege separation** between three execution contexts, each operating under fundamentally different trust levels. This architecture ensures that a compromise in any single layer cannot escalate to full system access.
|
The desktop wrapper enforces a **strict privilege separation** between three execution contexts, each operating under fundamentally different trust levels. This architecture ensures that a compromise in any single layer cannot escalate to full system access. The model is built on [Electron](https://www.electronjs.org/)'s security primitives: [`contextBridge`](https://www.electronjs.org/docs/latest/api/context-bridge), [`ipcMain`](https://www.electronjs.org/docs/latest/api/ipc-main), and [`ipcRenderer`](https://www.electronjs.org/docs/latest/api/ipc-renderer).
|
||||||
|
|
||||||
### Trust Level Matrix
|
### Trust Level Matrix
|
||||||
|
|
||||||
@@ -98,7 +104,7 @@ These settings are declared in `BrowserWindow.webPreferences` and are **non-nego
|
|||||||
| ------------------ | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
| ------------------ | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| `contextIsolation` | `true` | The Preload executes in a hermetically sealed V8 context. The renderer **cannot** access `require()`, Node.js globals, or any variable from the preload's scope. |
|
| `contextIsolation` | `true` | The Preload executes in a hermetically sealed V8 context. The renderer **cannot** access `require()`, Node.js globals, or any variable from the preload's scope. |
|
||||||
| `nodeIntegration` | `false` | **Zero** Node.js API surface in the renderer. `fs`, `child_process`, `os`, `net`, and all built-in modules are completely unavailable. |
|
| `nodeIntegration` | `false` | **Zero** Node.js API surface in the renderer. `fs`, `child_process`, `os`, `net`, and all built-in modules are completely unavailable. |
|
||||||
| `sandbox` | `true` | The renderer process runs inside a **Chromium OS-level sandbox**, restricting system calls and file access at the kernel level. |
|
| `sandbox` | `true` | The renderer process runs inside a **[Chromium OS-level sandbox](https://chromium.googlesource.com/chromium/src/+/HEAD/docs/design/sandbox.md)**, restricting system calls and file access at the kernel level. |
|
||||||
| `webSecurity` | `true` | The same-origin policy is **strictly enforced**, preventing cross-origin data exfiltration from the renderer. |
|
| `webSecurity` | `true` | The same-origin policy is **strictly enforced**, preventing cross-origin data exfiltration from the renderer. |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
# Desktop
|
# Desktop
|
||||||
|
> **Architectural Foundation:** [Electron](https://www.electronjs.org/) · [electron-vite](https://electron-vite.org/) · [electron-builder](https://www.electron.build/) · [electron-updater](https://www.npmjs.com/package/electron-updater)
|
||||||
|
>
|
||||||
|
> **Description:** Secure Electron desktop wrapper that embeds monorepo web applications, providing custom app:// protocol routing, hardware IPC bridge, auto-updates, and CORS bypass proxy with hardened security defaults.
|
||||||
|
|
||||||
The native gateway for our monorepo applications.
|
The native gateway for our monorepo applications.
|
||||||
|
|
||||||
> This package serves as a secure, high-performance Electron wrapper that transforms our web-based assets into first-class desktop experiences. Built on top of **electron-vite** for near-instant development cycles and **electron-builder** for seamless cross-platform distribution.
|
> This package serves as a secure, high-performance [Electron](https://www.electronjs.org/) wrapper that transforms our web-based assets into first-class desktop experiences. Built on top of **[electron-vite](https://electron-vite.org/)** for near-instant development cycles and **[electron-builder](https://www.electron.build/)** for seamless cross-platform distribution.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -140,7 +143,7 @@ Enables granular control over system peripherals — such as printers — throug
|
|||||||
|
|
||||||
### 🔄 Auto-Update Engine
|
### 🔄 Auto-Update Engine
|
||||||
|
|
||||||
A fully managed update lifecycle powered by `electron-updater`. Background download progress is forwarded in real-time to the React UI via IPC event subscriptions, enabling rich notification experiences. See [AUTO_UPDATER.md](./AUTO_UPDATER.md).
|
A fully managed update lifecycle powered by [`electron-updater`](https://www.npmjs.com/package/electron-updater). Background download progress is forwarded in real-time to the React UI via IPC event subscriptions, enabling rich notification experiences. See [AUTO_UPDATER.md](./AUTO_UPDATER.md).
|
||||||
|
|
||||||
### 🛡️ CORS Bypass Proxy
|
### 🛡️ CORS Bypass Proxy
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
# Monorepo Architecture Overview
|
# Monorepo Architecture Overview
|
||||||
|
|
||||||
|
> **Architectural Foundation:** [Turborepo](https://turbo.build/repo) · [pnpm](https://pnpm.io/) · [Vite](https://vite.dev/) · [TypeScript](https://www.typescriptlang.org/)
|
||||||
|
>
|
||||||
|
> **Description:** Architectural overview of the monorepo, orchestrated by Turborepo with pnpm workspaces, housing React/Vite applications and shared TypeScript packages.
|
||||||
|
|
||||||
## 📂 Repository Structure
|
## 📂 Repository Structure
|
||||||
|
|
||||||
The monorepo is organized into **Apps** (deployable applications) and **Packages** (shared libraries).
|
The monorepo is organized into **Apps** (deployable applications) and **Packages** (shared libraries).
|
||||||
@@ -37,10 +41,10 @@ The main consumer-facing application.
|
|||||||
|
|
||||||
**Tech Stack**:
|
**Tech Stack**:
|
||||||
|
|
||||||
* React
|
* [React](https://react.dev/)
|
||||||
* Vite
|
* [Vite](https://vite.dev/)
|
||||||
* TypeScript
|
* [TypeScript](https://www.typescriptlang.org/)
|
||||||
* Tailwind CSS
|
* [Tailwind CSS](https://tailwindcss.com/)
|
||||||
|
|
||||||
### 2. `apps/desktop`
|
### 2. `apps/desktop`
|
||||||
The **Electron desktop wrapper** that embeds `apps/web` for native desktop experiences.
|
The **Electron desktop wrapper** that embeds `apps/web` for native desktop experiences.
|
||||||
@@ -51,10 +55,10 @@ The **Electron desktop wrapper** that embeds `apps/web` for native desktop exper
|
|||||||
|
|
||||||
**Tech Stack**:
|
**Tech Stack**:
|
||||||
|
|
||||||
* Electron 33.x
|
* [Electron](https://www.electronjs.org/) 33.x
|
||||||
* electron-vite
|
* [electron-vite](https://electron-vite.org/)
|
||||||
* electron-builder
|
* [electron-builder](https://www.electron.build/)
|
||||||
* electron-updater
|
* [electron-updater](https://www.npmjs.com/package/electron-updater)
|
||||||
|
|
||||||
**Key Capabilities**:
|
**Key Capabilities**:
|
||||||
|
|
||||||
@@ -69,25 +73,25 @@ The **Electron desktop wrapper** that embeds `apps/web` for native desktop exper
|
|||||||
### 3. `apps/landing`
|
### 3. `apps/landing`
|
||||||
The **public promotional website** — a standalone SPA for the company profile and marketing pages.
|
The **public promotional website** — a standalone SPA for the company profile and marketing pages.
|
||||||
|
|
||||||
* Deployed independently to the web (e.g., Vercel) — no interaction with Electron
|
* Deployed independently to the web (e.g., [Vercel](https://vercel.com/)) — no interaction with Electron
|
||||||
* Consumes shared UI components from `@repo/ui` and utilities from `@repo/utils`
|
* Consumes shared UI components from `@repo/ui` and utilities from `@repo/utils`
|
||||||
* Locked to port **3000** (`strictPort: true`) — evacuated from the `517x` range to avoid `electron-vite` port collisions
|
* Locked to port **3000** (`strictPort: true`) — evacuated from the `517x` range to avoid `electron-vite` port collisions
|
||||||
|
|
||||||
**Tech Stack**:
|
**Tech Stack**:
|
||||||
|
|
||||||
* React
|
* [React](https://react.dev/)
|
||||||
* Vite
|
* [Vite](https://vite.dev/)
|
||||||
* TypeScript
|
* [TypeScript](https://www.typescriptlang.org/)
|
||||||
* Tailwind CSS v4
|
* [Tailwind CSS](https://tailwindcss.com/) v4
|
||||||
|
|
||||||
### 4. `apps/docs-dev`
|
### 4. `apps/docs-dev`
|
||||||
An isolated environment for developing and documenting UI components.
|
An isolated environment for developing and documenting UI components.
|
||||||
* Ensures components in `@repo/ui` are built and tested independently
|
* Ensures components in `@repo/ui` are built and tested independently
|
||||||
* Acts as a living design system and playground
|
* Acts as a living design system and playground
|
||||||
* Built with **VitePress**
|
* Built with **[VitePress](https://vitepress.dev/)**
|
||||||
|
|
||||||
### 5. `packages/core-api`
|
### 5. `packages/core-api`
|
||||||
The **platform-agnostic API engine** for the monorepo. Provides an isolated HTTP client factory, a unified observability pipeline (Grafana Faro + OpenTelemetry), and a generic data services engine.
|
The **platform-agnostic API engine** for the monorepo. Provides an isolated HTTP client factory, a unified observability pipeline ([Grafana Faro](https://grafana.com/docs/grafana-cloud/monitor-applications/frontend-observability/faro-web-sdk/) + [OpenTelemetry](https://opentelemetry.io/)), and a generic data services engine.
|
||||||
|
|
||||||
* Consumed by `apps/web`, `apps/landing`, and any future workspace
|
* Consumed by `apps/web`, `apps/landing`, and any future workspace
|
||||||
* Centralizes all `@grafana/faro-*` and `@opentelemetry/*` dependencies
|
* Centralizes all `@grafana/faro-*` and `@opentelemetry/*` dependencies
|
||||||
@@ -95,10 +99,10 @@ The **platform-agnostic API engine** for the monorepo. Provides an isolated HTTP
|
|||||||
|
|
||||||
**Tech Stack**:
|
**Tech Stack**:
|
||||||
|
|
||||||
* Axios (isolated instances, zero singleton pollution)
|
* [Axios](https://axios-http.com/) (isolated instances, zero singleton pollution)
|
||||||
* Grafana Faro (RUM, Logs, Error tracking)
|
* [Grafana Faro](https://grafana.com/docs/grafana-cloud/monitor-applications/frontend-observability/faro-web-sdk/) (RUM, Logs, Error tracking)
|
||||||
* OpenTelemetry (custom spans, distributed tracing)
|
* [OpenTelemetry](https://opentelemetry.io/) (custom spans, distributed tracing)
|
||||||
* TypeScript (strict types, module augmentation)
|
* [TypeScript](https://www.typescriptlang.org/) (strict types, module augmentation)
|
||||||
|
|
||||||
**Key Capabilities**:
|
**Key Capabilities**:
|
||||||
|
|
||||||
@@ -131,7 +135,7 @@ Provides a Hybrid Namespace Architecture combining a centralized i18n engine wit
|
|||||||
### 8. `packages/core-events`
|
### 8. `packages/core-events`
|
||||||
The **decoupled Nervous System** for the monorepo.
|
The **decoupled Nervous System** for the monorepo.
|
||||||
|
|
||||||
Provides a highly performant, strictly typed Event Bus (Pub/Sub) powered by `mitt`. It allows independent modules to communicate seamlessly without tightly coupling their codebases or triggering expensive global React tree re-renders.
|
Provides a highly performant, strictly typed Event Bus (Pub/Sub) powered by [`mitt`](https://www.npmjs.com/package/mitt). It allows independent modules to communicate seamlessly without tightly coupling their codebases or triggering expensive global React tree re-renders.
|
||||||
|
|
||||||
**Key Capabilities**:
|
**Key Capabilities**:
|
||||||
|
|
||||||
@@ -143,7 +147,7 @@ Provides a highly performant, strictly typed Event Bus (Pub/Sub) powered by `mit
|
|||||||
| 🛡️ Strict Contracts | Centralized `events.registry.ts` enforces payload shapes via TypeScript, ensuring cross-module data safety. |
|
| 🛡️ Strict Contracts | Centralized `events.registry.ts` enforces payload shapes via TypeScript, ensuring cross-module data safety. |
|
||||||
|
|
||||||
### 9. `packages/utils`
|
### 9. `packages/utils`
|
||||||
Shared business logic and reusable utility modules that can be consumed across multiple applications. Fully tested using Vitest.
|
Shared business logic and reusable utility modules that can be consumed across multiple applications. Fully tested using [Vitest](https://vitest.dev/).
|
||||||
|
|
||||||
This package is intended to hold non-UI, cross-cutting logic such as date/time handling, security helpers, and other common utilities. It is designed to be framework-agnostic, predictable, and easy to extend as the system evolves.
|
This package is intended to hold non-UI, cross-cutting logic such as date/time handling, security helpers, and other common utilities. It is designed to be framework-agnostic, predictable, and easy to extend as the system evolves.
|
||||||
|
|
||||||
@@ -152,17 +156,17 @@ Shared UI component library (Buttons, Inputs, Cards, Layouts) with a comprehensi
|
|||||||
|
|
||||||
* Ensures consistent design across all applications
|
* Ensures consistent design across all applications
|
||||||
* Designed to be consumed by both web apps and Storybook
|
* Designed to be consumed by both web apps and Storybook
|
||||||
* **Form UI Library**: 22 RHF-connected Mantine form components with Zod validation and i18n error translation, built via a `withRHF()` HOC factory with `useController` micro-subscriptions and `React.memo` optimization for ERP-scale forms
|
* **Form UI Library**: 22 RHF-connected [Mantine](https://mantine.dev/) form components with [Zod](https://zod.dev/) validation and i18n error translation, built via a `withRHF()` HOC factory with `useController` micro-subscriptions and `React.memo` optimization for ERP-scale forms
|
||||||
|
|
||||||
### 11. `packages/configs`
|
### 11. `packages/configs`
|
||||||
Single source of truth for tooling configuration.
|
Single source of truth for tooling configuration.
|
||||||
* **eslint-config**: Shared ESLint rules
|
* **eslint-config**: Shared [ESLint](https://eslint.org/) rules
|
||||||
* **typescript-config**: Shared `tsconfig.json` base configurations
|
* **typescript-config**: Shared `tsconfig.json` base configurations
|
||||||
|
|
||||||
## ⚙️ Configuration & Environment
|
## ⚙️ Configuration & Environment
|
||||||
|
|
||||||
### Turborepo Caching
|
### Turborepo Caching
|
||||||
This repository uses **Turborepo caching** for builds, tests, and other artifacts.
|
This repository uses **[Turborepo](https://turbo.build/repo) caching** for builds, tests, and other artifacts.
|
||||||
To fully clean the workspace (dependencies, build outputs, and Turbo cache):
|
To fully clean the workspace (dependencies, build outputs, and Turbo cache):
|
||||||
```bash
|
```bash
|
||||||
rm -rf node_modules **/*/node_modules .turbo **/*/.turbo dist **/*/dist out **/*/out web-dist **/*/web-dist release **/*/release
|
rm -rf node_modules **/*/node_modules .turbo **/*/.turbo dist **/*/dist out **/*/out web-dist **/*/web-dist release **/*/release
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
|
|
||||||
# Enterprise API Engine (`@repo/core-api`)
|
# Enterprise API Engine (`@repo/core-api`)
|
||||||
|
|
||||||
The platform-agnostic API engine for the monorepo. Provides an isolated HTTP client factory, a unified observability pipeline (Grafana Faro + OpenTelemetry), and a generic data services engine.
|
> **Architectural Foundation:** [Axios](https://axios-http.com/) · [Grafana Faro](https://grafana.com/docs/grafana-cloud/monitor-applications/frontend-observability/faro-web-sdk/) · [OpenTelemetry](https://opentelemetry.io/)
|
||||||
|
>
|
||||||
|
> **Description:** Platform-agnostic API engine providing isolated Axios HTTP client factories, a Grafana Faro + OpenTelemetry observability pipeline, and a generic CRUD data services layer.
|
||||||
|
|
||||||
|
The platform-agnostic API engine for the monorepo. Provides an isolated HTTP client factory, a unified observability pipeline ([Grafana Faro](https://grafana.com/docs/grafana-cloud/monitor-applications/frontend-observability/faro-web-sdk/) + [OpenTelemetry](https://opentelemetry.io/)), and a generic data services engine.
|
||||||
|
|
||||||
**This package enforces App Autonomy (IoC).** The core provides the engine and interceptor pipelines, but the consuming applications (`apps/web`, `apps/landing`) inject their own specific configurations, authentication tokens, and error handling behaviors.
|
**This package enforces App Autonomy (IoC).** The core provides the engine and interceptor pipelines, but the consuming applications (`apps/web`, `apps/landing`) inject their own specific configurations, authentication tokens, and error handling behaviors.
|
||||||
|
|
||||||
@@ -122,7 +125,7 @@ sequenceDiagram
|
|||||||
|
|
||||||
### `createHttpClient(config, hooks?)`
|
### `createHttpClient(config, hooks?)`
|
||||||
|
|
||||||
Creates an **isolated** Axios instance. Each app receives its own interceptor chain — no globals are shared or mutated.
|
Creates an **isolated** [Axios](https://axios-http.com/) instance. Each app receives its own interceptor chain — no globals are shared or mutated.
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
import { createHttpClient } from '@repo/core-api/http-client';
|
import { createHttpClient } from '@repo/core-api/http-client';
|
||||||
@@ -179,7 +182,7 @@ The observability layer operates in two complementary modes:
|
|||||||
| Mode | Activation | What it does |
|
| Mode | Activation | What it does |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| **Baseline** (always on) | Automatic | Pushes structured logs to Faro/Loki on every request with `module.key`, `module.action`, HTTP method, and URL |
|
| **Baseline** (always on) | Automatic | Pushes structured logs to Faro/Loki on every request with `module.key`, `module.action`, HTTP method, and URL |
|
||||||
| **Custom Span** (opt-in) | Via `telemetryContext.customSpanName` | Creates an explicit OTel span with custom tags, visible in Grafana Tempo |
|
| **Custom Span** (opt-in) | Via `telemetryContext.customSpanName` | Creates an explicit OTel span with custom tags, visible in [Grafana Tempo](https://grafana.com/oss/tempo/) |
|
||||||
|
|
||||||
> [!NOTE]
|
> [!NOTE]
|
||||||
> `trace.getActiveSpan()` returns `undefined` inside Axios interceptors due to browser XHR/Fetch lifecycle race conditions with Faro's `TracingInstrumentation`. The adapter does **not** attempt to enrich auto-instrumented spans. HTTP span capture is handled entirely by `TracingInstrumentation` auto-instrumentation.
|
> `trace.getActiveSpan()` returns `undefined` inside Axios interceptors due to browser XHR/Fetch lifecycle race conditions with Faro's `TracingInstrumentation`. The adapter does **not** attempt to enrich auto-instrumented spans. HTTP span capture is handled entirely by `TracingInstrumentation` auto-instrumentation.
|
||||||
@@ -221,7 +224,7 @@ Every request dispatched through `BaseRemoteDataServices` automatically attaches
|
|||||||
| `ex-module-key` | `DataServicesConfig.moduleKey` | Identifies the business module (e.g., `BOOKING`) |
|
| `ex-module-key` | `DataServicesConfig.moduleKey` | Identifies the business module (e.g., `BOOKING`) |
|
||||||
| `ex-module-action` | `RequestDescriptor.action` | Identifies the operation (e.g., `READ`, `CREATE`) |
|
| `ex-module-action` | `RequestDescriptor.action` | Identifies the operation (e.g., `READ`, `CREATE`) |
|
||||||
|
|
||||||
These headers are extracted by the `faroAdapter` and included in all Faro `pushLog`, `pushError`, and `pushEvent` calls as top-level context — making them directly queryable in **LogQL (Loki)**.
|
These headers are extracted by the `faroAdapter` and included in all Faro `pushLog`, `pushError`, and `pushEvent` calls as top-level context — making them directly queryable in **LogQL ([Loki](https://grafana.com/oss/loki/))**.
|
||||||
|
|
||||||
### Span Safety Guarantees
|
### Span Safety Guarantees
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
|
|
||||||
# Event Bus (`@repo/core-events`)
|
# Event Bus (`@repo/core-events`)
|
||||||
|
|
||||||
|
> **Architectural Foundation:** [mitt](https://www.npmjs.com/package/mitt)
|
||||||
|
>
|
||||||
|
> **Description:** Strictly-typed global event bus powered by mitt, enabling decoupled pub/sub communication across React components with automatic memory-safe lifecycle cleanup.
|
||||||
|
|
||||||
The Global Pub/Sub & Hardware Integration Blueprint.
|
The Global Pub/Sub & Hardware Integration Blueprint.
|
||||||
|
|
||||||
> This module provides a strictly-typed, global event bus for the monorepo ecosystem. It decouples cross-component communication and manages real-time hardware signals (such as printers and POS peripherals), ensuring a reactive and memory-safe architecture across all applications.
|
> This module provides a strictly-typed, global event bus for the monorepo ecosystem. It decouples cross-component communication and manages real-time hardware signals (such as printers and POS peripherals), ensuring a reactive and memory-safe architecture across all applications.
|
||||||
@@ -9,7 +12,7 @@ The Global Pub/Sub & Hardware Integration Blueprint.
|
|||||||
|
|
||||||
## 🧠 System Overview
|
## 🧠 System Overview
|
||||||
|
|
||||||
`@repo/core-events` is the **decoupled Nervous System** of the ERP. It provides a highly performant, strictly-typed Event Bus powered by `mitt` and custom React hooks.
|
`@repo/core-events` is the **decoupled Nervous System** of the ERP. It provides a highly performant, strictly-typed Event Bus powered by [`mitt`](https://www.npmjs.com/package/mitt) and custom [React](https://react.dev/) hooks.
|
||||||
|
|
||||||
**This package is a pure tool.** It ships zero application-specific events. Each consuming app (`apps/web`, `apps/desktop`, etc.) registers its own events autonomously using **TypeScript Declaration Merging** — the exact same Inversion of Control (IoC) pattern utilized by our `@repo/core-api` factory and `@repo/core-storage` engine.
|
**This package is a pure tool.** It ships zero application-specific events. Each consuming app (`apps/web`, `apps/desktop`, etc.) registers its own events autonomously using **TypeScript Declaration Merging** — the exact same Inversion of Control (IoC) pattern utilized by our `@repo/core-api` factory and `@repo/core-storage` engine.
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
|
|
||||||
# i18n Architecture (`@repo/core-i18n`)
|
# i18n Architecture (`@repo/core-i18n`)
|
||||||
|
|
||||||
|
> **Architectural Foundation:** [i18next](https://www.i18next.com/) · [react-i18next](https://react.i18next.com/)
|
||||||
|
>
|
||||||
|
> **Description:** Hybrid namespace internationalization engine built on i18next, providing centralized common vocabularies with lazy-loaded feature dictionaries, tenant overrides, and backend sync with automatic rollback.
|
||||||
|
|
||||||
A highly decoupled, type-safe internationalization engine for the monorepo.
|
A highly decoupled, type-safe internationalization engine for the monorepo.
|
||||||
|
|
||||||
It uses a **Hybrid Namespace Strategy**:
|
It uses a **Hybrid Namespace Strategy**:
|
||||||
|
|||||||
@@ -1,14 +1,17 @@
|
|||||||
|
|
||||||
# Storage Engine (`@repo/core-storage`)
|
# Storage Engine (`@repo/core-storage`)
|
||||||
|
|
||||||
|
> **Architectural Foundation:** [PouchDB](https://pouchdb.com/) · [CouchDB](https://couchdb.apache.org/) · [IndexedDB API (MDN)](https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API)
|
||||||
|
>
|
||||||
|
> **Description:** Enterprise storage engine providing AES-encrypted LocalStorage, strict-gatekeeper IndexedDB, and offline-first PouchDB with bi-directional CouchDB cloud synchronization.
|
||||||
|
|
||||||
`@repo/core-storage` is the **Enterprise-grade, multi-tool storage engine** for the Eigen Monorepo.
|
`@repo/core-storage` is the **Enterprise-grade, multi-tool storage engine** for the Eigen Monorepo.
|
||||||
|
|
||||||
It provides a unified set of strictly-typed, secure, and fault-tolerant storage mechanisms tailored for React applications. It enforces strict **Inversion of Control (IoC)**—the core engine knows absolutely nothing about your application's business domains; instead, the consuming apps inject their own configurations and types.
|
It provides a unified set of strictly-typed, secure, and fault-tolerant storage mechanisms tailored for React applications. It enforces strict **Inversion of Control (IoC)**—the core engine knows absolutely nothing about your application's business domains; instead, the consuming apps inject their own configurations and types.
|
||||||
|
|
||||||
This package provides three primary storage solutions:
|
This package provides three primary storage solutions:
|
||||||
1. **Secure Local Storage** (Strict Key-Gatekeeping & AES encryption)
|
1. **Secure Local Storage** (Strict Key-Gatekeeping & AES encryption)
|
||||||
2. **Secure IndexedDB** (For larger key-value payloads)
|
2. **Secure [IndexedDB](https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API)** (For larger key-value payloads)
|
||||||
3. **Offline-First PouchDB** (For document-oriented, bi-directional sync data)
|
3. **Offline-First [PouchDB](https://pouchdb.com/)** (For document-oriented, bi-directional sync data)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -113,7 +116,7 @@ const theme = await appStorage.getItem('THEME'); // Plaintext on disk
|
|||||||
|
|
||||||
## 🔄 Offline-First Document Storage (PouchDB & CouchDB)
|
## 🔄 Offline-First Document Storage (PouchDB & CouchDB)
|
||||||
|
|
||||||
For complex, document-oriented data that requires fault-tolerance, offline support, and bi-directional cloud synchronization, we use the `PouchDatabaseManager`.
|
For complex, document-oriented data that requires fault-tolerance, offline support, and bi-directional cloud synchronization, we use the `PouchDatabaseManager`. This layer is powered by [PouchDB](https://pouchdb.com/) syncing to [CouchDB](https://couchdb.apache.org/).
|
||||||
|
|
||||||
### Architecture
|
### Architecture
|
||||||
|
|
||||||
|
|||||||
@@ -4,8 +4,12 @@ outline: [2, 3]
|
|||||||
|
|
||||||
# Core App Shell — Layout Engine
|
# Core App Shell — Layout Engine
|
||||||
|
|
||||||
|
> **Architectural Foundation:** [Mantine AppShell](https://mantine.dev/core/app-shell/) · [@mantine/hooks](https://mantine.dev/hooks/package/)
|
||||||
|
>
|
||||||
|
> **Description:** Configuration-driven layout engine wrapping Mantine's AppShell, providing three layout variants (header-first, sidebar-first, top-nav), double sidebar support, responsive mobile drawers, and state persistence via Context API.
|
||||||
|
|
||||||
> **Package**: `@repo/ui` · **Module Path**: `@repo/ui/components`
|
> **Package**: `@repo/ui` · **Module Path**: `@repo/ui/components`
|
||||||
> **Dependencies**: React 18+, Mantine v8 (`AppShell`), `@mantine/hooks`
|
> **Dependencies**: React 18+, [Mantine v8](https://mantine.dev/) (`AppShell`), [`@mantine/hooks`](https://mantine.dev/hooks/package/)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -4,8 +4,12 @@ outline: [2, 3]
|
|||||||
|
|
||||||
# Form UI Library
|
# Form UI Library
|
||||||
|
|
||||||
|
> **Architectural Foundation:** [React Hook Form v7](https://react-hook-form.com/) · [Zod v3](https://zod.dev/) · [Mantine v8](https://mantine.dev/) · [@hookform/resolvers](https://www.npmjs.com/package/@hookform/resolvers) · [@mantine/tiptap](https://mantine.dev/x/tiptap/)
|
||||||
|
>
|
||||||
|
> **Description:** 22 pre-built form field components generated via a withRHF() HOC factory, integrating Mantine inputs with React Hook Form micro-subscriptions, Zod validation, and i18n error translation for ERP-scale performance.
|
||||||
|
|
||||||
> **Package**: `@repo/ui` · **Module Path**: `@repo/ui/form`
|
> **Package**: `@repo/ui` · **Module Path**: `@repo/ui/form`
|
||||||
> **Dependencies**: React Hook Form v7, Zod v3, Mantine v8, `@repo/core-i18n`
|
> **Dependencies**: [React Hook Form](https://react-hook-form.com/) v7, [Zod](https://zod.dev/) v3, [Mantine](https://mantine.dev/) v8, `@repo/core-i18n`
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -898,7 +902,7 @@ export const FieldDatePicker = withRHF<DatePickerInputProps>(
|
|||||||
| `FieldRichTextEditor` | `@mantine/tiptap` | `string` (HTML) |
|
| `FieldRichTextEditor` | `@mantine/tiptap` | `string` (HTML) |
|
||||||
|
|
||||||
### Rich Text Editor (TipTap)
|
### Rich Text Editor (TipTap)
|
||||||
The `FieldRichTextEditor` component integrates `@mantine/tiptap` directly with React Hook Form. It safely stores the Editor's HTML output directly into the RHF state as a `string`. Because TipTap is an uncontrolled editor natively, this field uses a specialized `useController` wrapper that automatically syncs bidirectional updates (e.g., calling `editor.commands.setContent(field.value)` when the form is reset or async default values arrive).
|
The `FieldRichTextEditor` component integrates [`@mantine/tiptap`](https://mantine.dev/x/tiptap/) directly with React Hook Form. It safely stores the Editor's HTML output directly into the RHF state as a `string`. Because TipTap is an uncontrolled editor natively, this field uses a specialized `useController` wrapper that automatically syncs bidirectional updates (e.g., calling `editor.commands.setContent(field.value)` when the form is reset or async default values arrive).
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -1,14 +1,18 @@
|
|||||||
# @repo/ui — Shared UI Component Library
|
# @repo/ui — Shared UI Component Library
|
||||||
|
|
||||||
|
> **Architectural Foundation:** [Mantine v8](https://mantine.dev/) · [React Hook Form v7](https://react-hook-form.com/) · [Zod v3](https://zod.dev/) · [Tailwind CSS v4](https://tailwindcss.com/)
|
||||||
|
>
|
||||||
|
> **Description:** Shared UI component library providing Mantine-based design primitives, a ThemeProvider with density modes, and a 22-component Form UI Library with RHF + Zod validation and i18n error translation.
|
||||||
|
|
||||||
The centralized UI component library for the monorepo. Provides consistent design primitives, system pages, and **a comprehensive Form UI Library** for building enterprise-grade forms.
|
The centralized UI component library for the monorepo. Provides consistent design primitives, system pages, and **a comprehensive Form UI Library** for building enterprise-grade forms.
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
- **Mantine v8** components re-exported with unified theming
|
- **[Mantine v8](https://mantine.dev/)** components re-exported with unified theming
|
||||||
- **ThemeProvider** with dark/light mode, brand colors, and density modes (compact/standard)
|
- **ThemeProvider** with dark/light mode, brand colors, and density modes (compact/standard)
|
||||||
- **Design tokens** — Colors, typography, radius, spacing, shadows mapped between Mantine and Tailwind
|
- **Design tokens** — Colors, typography, radius, spacing, shadows mapped between Mantine and Tailwind
|
||||||
- **System pages** — Pre-built 404, 403, Maintenance, and Coming Soon pages
|
- **System pages** — Pre-built 404, 403, Maintenance, and Coming Soon pages
|
||||||
- **Form UI Library** — 22 RHF-connected Mantine form components with Zod validation and i18n error translation
|
- **Form UI Library** — 22 RHF-connected Mantine form components with [Zod](https://zod.dev/) validation and i18n error translation
|
||||||
|
|
||||||
## Exports
|
## Exports
|
||||||
|
|
||||||
@@ -74,7 +78,7 @@ function UserForm() {
|
|||||||
|
|
||||||
## Dependencies
|
## Dependencies
|
||||||
|
|
||||||
- `@mantine/core` v8, `@mantine/hooks` v8
|
- [`@mantine/core`](https://mantine.dev/) v8, [`@mantine/hooks`](https://mantine.dev/hooks/package/) v8
|
||||||
- `react-hook-form` v7, `@hookform/resolvers` v5, `zod` v3
|
- [`react-hook-form`](https://react-hook-form.com/) v7, [`@hookform/resolvers`](https://www.npmjs.com/package/@hookform/resolvers) v5, [`zod`](https://zod.dev/) v3
|
||||||
- `@repo/core-i18n` (workspace)
|
- `@repo/core-i18n` (workspace)
|
||||||
- `tailwindcss` v4, `tailwind-variants`, `tailwind-merge`
|
- [`tailwindcss`](https://tailwindcss.com/) v4, [`tailwind-variants`](https://www.tailwind-variants.org/), [`tailwind-merge`](https://www.npmjs.com/package/tailwind-merge)`
|
||||||
|
|||||||
@@ -1,13 +1,17 @@
|
|||||||
# Local Development Setup
|
# Local Development Setup
|
||||||
|
|
||||||
|
> **Architectural Foundation:** [Node.js](https://nodejs.org/) · [pnpm](https://pnpm.io/) · [Turborepo](https://turbo.build/repo)
|
||||||
|
>
|
||||||
|
> **Description:** Local development setup guide covering prerequisites (Node.js v20+, pnpm v8), workspace installation, and Turborepo-orchestrated development and build scripts.
|
||||||
|
|
||||||
## 🚀 Getting Started
|
## 🚀 Getting Started
|
||||||
|
|
||||||
### Prerequisites
|
### Prerequisites
|
||||||
|
|
||||||
Ensure your local environment matches the following versions to avoid compatibility issues:
|
Ensure your local environment matches the following versions to avoid compatibility issues:
|
||||||
|
|
||||||
* **Node.js**: `v20+` (tested with `v24.11.1`) — required for the `--import tsx` flag used by the desktop prebuild script
|
* **[Node.js](https://nodejs.org/)**: `v20+` (tested with `v24.11.1`) — required for the `--import tsx` flag used by the desktop prebuild script
|
||||||
* **pnpm**: `v8.15.6`
|
* **[pnpm](https://pnpm.io/)**: `v8.15.6`
|
||||||
(Enforced via the `packageManager` field in `package.json`)
|
(Enforced via the `packageManager` field in `package.json`)
|
||||||
|
|
||||||
### Installation
|
### Installation
|
||||||
@@ -20,7 +24,7 @@ pnpm install
|
|||||||
|
|
||||||
## 🛠 Usage & Scripts
|
## 🛠 Usage & Scripts
|
||||||
|
|
||||||
This repository uses **Turborepo** to orchestrate tasks efficiently. All commands are executed from the root.
|
This repository uses **[Turborepo](https://turbo.build/repo)** to orchestrate tasks efficiently. All commands are executed from the root.
|
||||||
|
|
||||||
### Development
|
### Development
|
||||||
|
|
||||||
@@ -29,7 +33,7 @@ This repository uses **Turborepo** to orchestrate tasks efficiently. All command
|
|||||||
| `pnpm dev` | Start **all applications** (`web` and `docs-dev`) in parallel |
|
| `pnpm dev` | Start **all applications** (`web` and `docs-dev`) in parallel |
|
||||||
| `pnpm dev:web` | Start only the **Main Web App** (strictly at `http://localhost:5173`) |
|
| `pnpm dev:web` | Start only the **Main Web App** (strictly at `http://localhost:5173`) |
|
||||||
| `pnpm dev:landing` | Start the **Public Landing App** (strictly at `http://localhost:3000`) |
|
| `pnpm dev:landing` | Start the **Public Landing App** (strictly at `http://localhost:3000`) |
|
||||||
| `pnpm dev:docs-dev` | Start **VitePress** for documentation development (strictly at `http://localhost:6060`) |
|
| `pnpm dev:docs-dev` | Start **[VitePress](https://vitepress.dev/)** for documentation development (strictly at `http://localhost:6060`) |
|
||||||
| `pnpm dev:desktop` | Start the **Web App + Electron** in parallel for desktop development |
|
| `pnpm dev:desktop` | Start the **Web App + Electron** in parallel for desktop development |
|
||||||
|
|
||||||
> [!NOTE]
|
> [!NOTE]
|
||||||
@@ -44,9 +48,9 @@ This repository uses **Turborepo** to orchestrate tasks efficiently. All command
|
|||||||
| `pnpm build:landing` | Build only the landing page |
|
| `pnpm build:landing` | Build only the landing page |
|
||||||
| `pnpm build:docs-dev` | Build only the docs-dev application |
|
| `pnpm build:docs-dev` | Build only the docs-dev application |
|
||||||
| `pnpm build:desktop` | Build the web app, then compile the Electron app |
|
| `pnpm build:desktop` | Build the web app, then compile the Electron app |
|
||||||
| `pnpm test` | Run unit tests (Vitest) across all packages |
|
| `pnpm test` | Run unit tests ([Vitest](https://vitest.dev/)) across all packages |
|
||||||
| `pnpm lint` | Run ESLint across the workspace |
|
| `pnpm lint` | Run [ESLint](https://eslint.org/) across the workspace |
|
||||||
| `pnpm format` | Format code using Prettier |
|
| `pnpm format` | Format code using [Prettier](https://prettier.io/) |
|
||||||
|
|
||||||
### 🚀 Desktop Packaging & Distribution
|
### 🚀 Desktop Packaging & Distribution
|
||||||
|
|
||||||
@@ -64,7 +68,7 @@ To package the application into a production-ready installer, use the following
|
|||||||
>
|
>
|
||||||
> 1. **`turbo run build --filter=web`** — Compiles the React SPA into `apps/web/dist/`.
|
> 1. **`turbo run build --filter=web`** — Compiles the React SPA into `apps/web/dist/`.
|
||||||
> 2. **`prebuild` hook** — Runs `node --import tsx scripts/copy-web-dist.ts`, which copies `apps/web/dist/` → `apps/desktop/web-dist/`.
|
> 2. **`prebuild` hook** — Runs `node --import tsx scripts/copy-web-dist.ts`, which copies `apps/web/dist/` → `apps/desktop/web-dist/`.
|
||||||
> 3. **`electron-builder`** — Bundles `web-dist/` into the packaged app via the `files` and `extraResources` blocks in `electron-builder.yml`.
|
> 3. **[`electron-builder`](https://www.electron.build/)** — Bundles `web-dist/` into the packaged app via the `files` and `extraResources` blocks in `electron-builder.yml`.
|
||||||
>
|
>
|
||||||
> You do not need to run these steps manually — they are chained via npm scripts.
|
> You do not need to run these steps manually — they are chained via npm scripts.
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user