Merge pull request 'docs/dev' (#19) from docs/dev into main
Reviewed-on: eigen/fe-monorepo-template#19
This commit is contained in:
@@ -14,14 +14,19 @@
|
|||||||
},
|
},
|
||||||
|
|
||||||
// ─── Port Topology ──────────────────────────────────────────────────────────
|
// ─── Port Topology ──────────────────────────────────────────────────────────
|
||||||
// 6006: Storybook (Docs)
|
// 6060: VitePress Docs (Development)
|
||||||
|
// 4173: VitePress Docs (Preview)
|
||||||
// 5173: Web App (Must be strictly 5173 for Electron IPC compatibility)
|
// 5173: Web App (Must be strictly 5173 for Electron IPC compatibility)
|
||||||
// 3000: Landing App (Isolated from Vite's default 517x blast radius)
|
// 3000: Landing App (Isolated from Vite's default 517x blast radius)
|
||||||
"forwardPorts": [6006, 5173, 3000],
|
"forwardPorts": [6060, 4173, 5173, 3000],
|
||||||
|
|
||||||
"portsAttributes": {
|
"portsAttributes": {
|
||||||
"6006": {
|
"6060": {
|
||||||
"label": "Storybook",
|
"label": "VitePress Docs",
|
||||||
|
"onAutoForward": "notify"
|
||||||
|
},
|
||||||
|
"4173": {
|
||||||
|
"label": "VitePress Preview",
|
||||||
"onAutoForward": "notify"
|
"onAutoForward": "notify"
|
||||||
},
|
},
|
||||||
"5173": {
|
"5173": {
|
||||||
|
|||||||
@@ -44,3 +44,7 @@ web-dist/
|
|||||||
|
|
||||||
# Legacy Code (if applicable)
|
# Legacy Code (if applicable)
|
||||||
legacy/
|
legacy/
|
||||||
|
|
||||||
|
# VitePress
|
||||||
|
**/.vitepress/cache/
|
||||||
|
**/.vitepress/dist/
|
||||||
@@ -10,324 +10,31 @@
|
|||||||

|

|
||||||
|
|
||||||
A **scalable, enterprise-ready Web & Desktop monorepo** built with **Turborepo**, **pnpm**, **Vite**, and **Electron**.
|
A **scalable, enterprise-ready Web & Desktop monorepo** built with **Turborepo**, **pnpm**, **Vite**, and **Electron**.
|
||||||
This repository is designed for long-term maintainability, featuring:
|
This repository is designed for long-term maintainability, featuring shared logic and UI libraries, centralized tooling configuration, turbo-powered task orchestration, and native desktop distribution with auto-updates.
|
||||||
|
|
||||||
* Shared logic and UI libraries
|
|
||||||
* Centralized tooling configuration
|
|
||||||
* Turbo-powered task orchestration and caching
|
|
||||||
* Native desktop distribution with auto-updates
|
|
||||||
* Dedicated documentation & component playground using Storybook
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 📂 Repository Structure
|
## 🌍 Global Context
|
||||||
|
|
||||||
The monorepo is organized into **Apps** (deployable applications) and **Packages** (shared libraries).
|
This repository utilizes a monorepo architecture to seamlessly share core systems, business logic, and UI components across multiple distribution targets (Web, Desktop, and Landing Page).
|
||||||
|
|
||||||
```text
|
### Topology Overview
|
||||||
.
|
|
||||||
├── apps/
|
* **`apps/`**: Deployable applications (`web`, `desktop`, `landing`, `docs-dev`).
|
||||||
│ ├── web/ # Main React Application (Vite + TypeScript)
|
* **`packages/`**: Shared libraries and core engines (`core-api`, `core-storage`, `ui`, `utils`, `configs`, etc.).
|
||||||
│ ├── landing/ # Public Promotional SPA (Vite + TypeScript)
|
|
||||||
│ ├── desktop/ # Electron Desktop Wrapper (electron-vite)
|
|
||||||
│ └── docs-dev/ # Component Documentation & Playground (Storybook)
|
|
||||||
│
|
|
||||||
├── packages/
|
|
||||||
│ ├── core-api/ # Shared HTTP Client, Observability & Data Services Engine
|
|
||||||
│ ├── core-storage/ # Enterprise Storage Engine (IndexedDB/localStorage + Encryption)
|
|
||||||
│ ├── core-i18n/ # Enterprise Internationalization Architecture
|
|
||||||
│ ├── ui/ # Shared UI Component Library
|
|
||||||
│ ├── utils/ # Shared Utilities (Date, Encryption, Core Logic, etc)
|
|
||||||
│ └── configs/ # Shared Tooling Configurations
|
|
||||||
│ ├── eslint/ # Shared ESLint rules
|
|
||||||
│ └── typescript/ # Shared TypeScript (tsconfig) bases
|
|
||||||
│
|
|
||||||
├── package.json # Root scripts and dependencies
|
|
||||||
├── pnpm-workspace.yaml # pnpm workspace definition
|
|
||||||
└── turbo.json # Turborepo pipeline configuration
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 🚀 Getting Started
|
## 📚 Single Source of Truth
|
||||||
|
|
||||||
### Prerequisites
|
|
||||||
|
|
||||||
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
|
|
||||||
* **pnpm**: `v8.15.6`
|
|
||||||
(Enforced via the `packageManager` field in `package.json`)
|
|
||||||
|
|
||||||
### Installation
|
|
||||||
|
|
||||||
Install all dependencies from the **root directory**:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
pnpm install
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🛠 Usage & Scripts
|
|
||||||
|
|
||||||
This repository uses **Turborepo** to orchestrate tasks efficiently. All commands are executed from the root.
|
|
||||||
|
|
||||||
### Development
|
|
||||||
|
|
||||||
| Command | Description |
|
|
||||||
| -------------------- | ---------------------------------------------------------------------------------- |
|
|
||||||
| `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:landing` | Start the **Public Landing App** (strictly at `http://localhost:3000`) |
|
|
||||||
| `pnpm dev:docs-dev` | Start **Storybook** for UI development (strictly at `http://localhost:6006`) |
|
|
||||||
| `pnpm dev:desktop` | Start the **Web App + Electron** in parallel for desktop development |
|
|
||||||
|
|
||||||
> [!NOTE]
|
|
||||||
> **Port Topology**: `electron-vite` dynamically allocates a background port (usually `5174`) for its internal renderer shell during `pnpm dev:desktop`. We strictly isolate `web` (`5173`) and `landing` (`3000`) onto separate port ranges to prevent race conditions during parallel execution.
|
|
||||||
|
|
||||||
### Building & Quality
|
|
||||||
|
|
||||||
| Command | Description |
|
|
||||||
| --------------------- | ------------------------------------------------------- |
|
|
||||||
| `pnpm build` | Build all apps and packages using Turbo cache |
|
|
||||||
| `pnpm build:web` | Build only the web application |
|
|
||||||
| `pnpm build:landing` | Build only the landing page |
|
|
||||||
| `pnpm build:docs-dev` | Build only the docs-dev application |
|
|
||||||
| `pnpm build:desktop` | Build the web app, then compile the Electron app |
|
|
||||||
| `pnpm test` | Run unit tests (Vitest) across all packages |
|
|
||||||
| `pnpm lint` | Run ESLint across the workspace |
|
|
||||||
| `pnpm format` | Format code using Prettier |
|
|
||||||
|
|
||||||
### 🚀 Desktop Packaging & Distribution
|
|
||||||
|
|
||||||
To package the application into a production-ready installer, use the following commands from the **root directory**:
|
|
||||||
|
|
||||||
| Command | Platform | Output Artifact |
|
|
||||||
| ---------------------- | ----------- | ------------------------------------------ |
|
|
||||||
| `pnpm package:desktop` | Current OS | Detects host OS and builds accordingly |
|
|
||||||
| `pnpm package:mac` | macOS | `.dmg` and `.zip` (supports x64 & arm64) |
|
|
||||||
| `pnpm package:win` | Windows | `.exe` (NSIS Installer) |
|
|
||||||
| `pnpm package:linux` | Linux | `.AppImage` |
|
|
||||||
|
|
||||||
> [!IMPORTANT]
|
> [!IMPORTANT]
|
||||||
> **Build Sequence**: All `package:*` commands execute the following pipeline automatically:
|
> **Internal Documentation Hub**
|
||||||
>
|
> All documentation, installation guides, architectural deep-dives, and API references are hosted internally via our VitePress application.
|
||||||
> 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/`.
|
|
||||||
> 3. **`electron-builder`** — 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.
|
|
||||||
|
|
||||||
> [!WARNING]
|
|
||||||
> **macOS Code Signing**: To build a distributable macOS app with Auto-Update support, you **must** have an Apple Developer Certificate and provide `CSC_LINK` and `CSC_KEY_PASSWORD` in your environment. Without code signing, macOS Gatekeeper will block the app and auto-updates will fail. See [AUTO_UPDATER.md](apps/desktop/docs/AUTO_UPDATER.md) for details.
|
|
||||||
|
|
||||||
> [!NOTE]
|
|
||||||
> **Cross-Compilation**: It is highly recommended to build for Windows on a Windows machine and for macOS on a Mac. Cross-compilation (e.g., building `.dmg` on Linux) may fail due to platform-specific toolchain dependencies. Use a CI matrix strategy (e.g., GitHub Actions with `runs-on: [macos-latest, windows-latest, ubuntu-latest]`) for multi-platform releases.
|
|
||||||
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📦 Packages Overview
|
|
||||||
|
|
||||||
### 1. `apps/web`
|
|
||||||
|
|
||||||
The main consumer-facing application.
|
|
||||||
|
|
||||||
* Imports business logic from `@repo/utils`
|
|
||||||
* Uses shared UI components from `@repo/ui`
|
|
||||||
|
|
||||||
**Tech Stack**:
|
|
||||||
|
|
||||||
* React
|
|
||||||
* Vite
|
|
||||||
* TypeScript
|
|
||||||
* Tailwind CSS
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 2. `apps/desktop`
|
|
||||||
|
|
||||||
The **Electron desktop wrapper** that embeds `apps/web` for native desktop experiences.
|
|
||||||
|
|
||||||
* In **development**: loads the Vite dev server with full hot reload
|
|
||||||
* In **production**: serves the static web build via a secure custom `app://` protocol
|
|
||||||
* Configurable target app via `.env` (can wrap `apps/web`, `apps/docs-dev`, or any future app)
|
|
||||||
|
|
||||||
**Tech Stack**:
|
|
||||||
|
|
||||||
* Electron 33.x
|
|
||||||
* electron-vite
|
|
||||||
* electron-builder
|
|
||||||
* electron-updater
|
|
||||||
|
|
||||||
**Key Capabilities**:
|
|
||||||
|
|
||||||
| Feature | Description |
|
|
||||||
|---|---|
|
|
||||||
| 🖨️ Native Printing | Silent and direct printing via secure IPC bridge |
|
|
||||||
| 🔄 Auto-Updates | Background downloads via GitHub Releases (switchable to S3) |
|
|
||||||
| 🔒 Secure IPC Bridge | `contextIsolation: true`, `nodeIntegration: false`, `sandbox: true` |
|
|
||||||
| 🌐 Custom Protocol | `app://` serves static files with SPA routing fallback to `index.html` |
|
|
||||||
| 🛡️ CORS Bypass | Transparent Origin header rewriting for cloud API calls |
|
|
||||||
|
|
||||||
**Desktop Documentation**:
|
|
||||||
|
|
||||||
| Document | Contents |
|
|
||||||
|---|---|
|
|
||||||
| [CONFIGURATION.md](apps/desktop/docs/CONFIGURATION.md) | Target app switching, `app://` protocol internals, HashRouter fallback |
|
|
||||||
| [AUTO_UPDATER.md](apps/desktop/docs/AUTO_UPDATER.md) | Release workflow, CI/CD variables, provider switching, code signing |
|
|
||||||
| [IPC_ARCHITECTURE.md](apps/desktop/docs/IPC_ARCHITECTURE.md) | Security model, Three-Step Bridge pattern, extending native features |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 3. `apps/landing`
|
|
||||||
|
|
||||||
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
|
|
||||||
* 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
|
|
||||||
|
|
||||||
**Tech Stack**:
|
|
||||||
|
|
||||||
* React
|
|
||||||
* Vite
|
|
||||||
* TypeScript
|
|
||||||
* Tailwind CSS v4
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 4. `apps/docs-dev` (Storybook)
|
|
||||||
|
|
||||||
An isolated environment for developing and documenting UI components.
|
|
||||||
|
|
||||||
* Ensures components in `@repo/ui` are built and tested independently
|
|
||||||
* Acts as a living design system and playground
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 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.
|
|
||||||
|
|
||||||
* Consumed by `apps/web`, `apps/landing`, and any future workspace
|
|
||||||
* Centralizes all `@grafana/faro-*` and `@opentelemetry/*` dependencies
|
|
||||||
* Provides plug-and-play telemetry via `initTelemetry()` + `faroAdapter`
|
|
||||||
|
|
||||||
**Tech Stack**:
|
|
||||||
|
|
||||||
* Axios (isolated instances, zero singleton pollution)
|
|
||||||
* Grafana Faro (RUM, Logs, Error tracking)
|
|
||||||
* OpenTelemetry (custom spans, distributed tracing)
|
|
||||||
* TypeScript (strict types, module augmentation)
|
|
||||||
|
|
||||||
**Key Capabilities**:
|
|
||||||
|
|
||||||
| Feature | Description |
|
|
||||||
|---|---|
|
|
||||||
| 🏭 HTTP Client Factory | `createHttpClient()` — per-app isolated Axios instances with interceptor hooks |
|
|
||||||
| 📡 Faro/Loki Baseline | Every request automatically pushes structured logs with `module.key` and `module.action` |
|
|
||||||
| 🎯 Custom Spans (Opt-In) | `telemetryContext.customSpanName` creates explicit OTel spans visible in Grafana Tempo |
|
|
||||||
| 🛡️ Error Normalization | `ApiError.fromAxiosError()` — structured, serializable error codes for all failure modes |
|
|
||||||
| 📦 Data Services Engine | `CommonRemoteDataServices` — full CRUD + lifecycle operations with zero boilerplate |
|
|
||||||
|
|
||||||
**Documentation**:
|
|
||||||
|
|
||||||
| Document | Contents |
|
|
||||||
|---|---|
|
|
||||||
| [README.md](packages/core-api/README.md) | Architecture, HTTP client setup, observability strategy, data services, app integration guide |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 6. `packages/core-storage`
|
|
||||||
|
|
||||||
The **Enterprise-grade storage engine** for the monorepo.
|
|
||||||
|
|
||||||
Provides a unified, Promise-based interface for interacting with browser storage (`localStorage` and `IndexedDB`). Enforces strict type safety, prevents key collisions via a centralized registry, and automatically provides **AES encryption at rest** for sensitive payloads using `@repo/utils`.
|
|
||||||
|
|
||||||
**Documentation**: [README.md](packages/core-storage/README.md)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 7. `packages/core-i18n`
|
|
||||||
|
|
||||||
The **Enterprise Internationalization Architecture** for the monorepo.
|
|
||||||
|
|
||||||
Provides a Hybrid Namespace Architecture combining a centralized i18n engine with decentralized, lazy-loaded feature dictionaries. Features strict TypeScript typings (including nested keys), optional backend synchronization with automatic error rollbacks, and a deep-merge mechanism for dynamic tenant-specific vocabulary overrides.
|
|
||||||
|
|
||||||
**Key Capabilities**:
|
|
||||||
|
|
||||||
| Feature | Description |
|
|
||||||
|---|---|
|
|
||||||
| 🌐 Hybrid Namespaces | Centralized `common` corpus + lazy-loaded feature dictionaries. |
|
|
||||||
| 🛡️ Strict Typings | Native TS autocomplete for nested paths (e.g., `header.title`) via module augmentation. |
|
|
||||||
| 🔄 Safe Backend Sync | `changeLanguage` accepts a `syncCallback` with built-in rollback if the API fails. |
|
|
||||||
| 🏢 Tenant Overrides | `applyTenantOverrides` performs a partial deep-merge to selectively override terminology. |
|
|
||||||
|
|
||||||
**Documentation**: [README.md](packages/core-i18n/README.md)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 8. `packages/core-events`
|
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
**Key Capabilities**:
|
|
||||||
|
|
||||||
| Feature | Description |
|
|
||||||
|---|---|
|
|
||||||
| 🧩 Zero Coupling | Publishers and subscribers interact via blind events, eliminating direct module imports and circular dependencies. |
|
|
||||||
| ⚡ Extreme Performance | Enables targeted DOM updates for high-frequency data streams (e.g., WebSockets) without re-rendering parent components. |
|
|
||||||
| 🧹 Memory Safety | Native `useAppEvent` hook automatically unsubscribes on component unmount, preventing SPA memory leaks. |
|
|
||||||
| 🛡️ Strict Contracts | Centralized `events.registry.ts` enforces payload shapes via TypeScript, ensuring cross-module data safety. |
|
|
||||||
|
|
||||||
**Documentation**: [README.md](packages/core-events/README.md)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 9. `packages/utils`
|
|
||||||
|
|
||||||
Shared business logic and reusable utility modules that can be consumed across multiple applications. Fully tested using Vitest.
|
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 10. `packages/ui`
|
|
||||||
|
|
||||||
Shared UI component library (Buttons, Inputs, Cards, Layouts) with a comprehensive **Form UI Library**.
|
|
||||||
|
|
||||||
* Ensures consistent design across all applications
|
|
||||||
* 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
|
|
||||||
|
|
||||||
**Documentation**: [README.md](packages/ui/README.md) · [Form Components Guide](packages/ui/docs/FORM-COMPONENTS.md)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 11. `packages/configs`
|
|
||||||
|
|
||||||
Single source of truth for tooling configuration.
|
|
||||||
|
|
||||||
* **eslint-config**: Shared ESLint rules (React, libraries, Storybook)
|
|
||||||
* **typescript-config**: Shared `tsconfig.json` base configurations
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## ⚙️ Configuration & Environment
|
|
||||||
|
|
||||||
|
|
||||||
### Turborepo Caching
|
|
||||||
|
|
||||||
This repository uses **Turborepo caching** for builds, tests, and other artifacts.
|
|
||||||
|
|
||||||
To fully clean the workspace (dependencies, build outputs, and Turbo cache):
|
|
||||||
|
|
||||||
|
* **View in Git Repository (Raw Markdown):** [Read Overview Documentation](apps/docs-dev/src/overview.md)
|
||||||
|
* **Run Documentation Locally:**
|
||||||
```bash
|
```bash
|
||||||
rm -rf node_modules **/*/node_modules .turbo **/*/.turbo dist **/*/dist out **/*/out web-dist **/*/web-dist release **/*/release
|
pnpm --filter docs-dev dev
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|||||||
@@ -1,29 +0,0 @@
|
|||||||
**Role:** You are a Staff Level React Engineer and Architect managing a highly scalable Enterprise ERP monorepo.
|
|
||||||
|
|
||||||
**Context:**
|
|
||||||
We have successfully established our Form UI library in `packages/ui/src/components/Form/fields` featuring 22 Mantine form components wrapped with React Hook Form (e.g., `FieldTextInput`, `FieldSelect`, `FieldColorPicker`, etc.). We also have a Zod validation layer at `packages/ui/src/validators` that uses JSON-stringified payloads for i18n translation.
|
|
||||||
We now need to build a showcase/demo page in the main web application to test and demonstrate these components in a real-world ERP form scenario.
|
|
||||||
|
|
||||||
**Pre-Execution Analysis (READ THESE FIRST):**
|
|
||||||
Before writing any code, you MUST read and analyze:
|
|
||||||
1. The component signatures and exports in `packages/ui/src/components/Form/index.ts`.
|
|
||||||
2. The Zod validator pattern in `packages/ui/src/validators` (specifically how the JSON i18n payloads are structured).
|
|
||||||
3. The existing layout and routing patterns in `apps/web/src/apps/showcase/showcase-view.tsx` to understand how to correctly inject and mount new showcase features.
|
|
||||||
|
|
||||||
**Task Requirements:**
|
|
||||||
|
|
||||||
**Phase 1: Create the Form Showcase Component**
|
|
||||||
1. Create a new comprehensive demo component inside `apps/web/src/apps/showcase/example/features/`. Follow the existing file naming convention found in that directory.
|
|
||||||
2. The component should implement a realistic ERP form (e.g., Textile Production Order, Inventory Bulk Update, or User Registration) using `useForm`, `zodResolver`, and a custom Zod schema.
|
|
||||||
3. The Zod schema MUST utilize the JSON-stringified i18n message pattern for validation errors.
|
|
||||||
4. Utilize a diverse set of our generated UI components (text input, select, number input, color input/picker, etc.) to prove they function correctly in a unified form.
|
|
||||||
5. Include a visual output panel (e.g., using Mantine's `Code` or `Pre` component) that displays the validated JSON payload upon successful submission.
|
|
||||||
|
|
||||||
**Phase 2: Connect to Showcase View**
|
|
||||||
1. Update `apps/web/src/apps/showcase/showcase-view.tsx` to import and render the newly created Form Showcase component.
|
|
||||||
2. Integrate it seamlessly into the existing UI layout of the showcase view (e.g., adding a new Tab, Accordion, or Section dedicated to the Form UI & Validation Layer).
|
|
||||||
|
|
||||||
**Execution Rules:**
|
|
||||||
- Do not rely on hardcoded assumptions. Let your code be guided completely by the patterns, styles, and typings you discover during the Pre-Execution Analysis.
|
|
||||||
- Ensure all TypeScript typings are strict.
|
|
||||||
- Output the newly created files and the modified files cleanly.
|
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
import { dirname, join, resolve } from 'path';
|
|
||||||
|
|
||||||
function getAbsolutePath(value) {
|
|
||||||
return dirname(require.resolve(join(value, 'package.json')));
|
|
||||||
}
|
|
||||||
|
|
||||||
const config = {
|
|
||||||
stories: ['../stories/*.stories.tsx', '../stories/**/*.stories.tsx'],
|
|
||||||
addons: [getAbsolutePath('@storybook/addon-links'), getAbsolutePath('@storybook/addon-essentials')],
|
|
||||||
framework: {
|
|
||||||
name: getAbsolutePath('@storybook/react-vite'),
|
|
||||||
options: {},
|
|
||||||
},
|
|
||||||
|
|
||||||
core: {},
|
|
||||||
|
|
||||||
async viteFinal(config, { configType }) {
|
|
||||||
// customize the Vite config here
|
|
||||||
return {
|
|
||||||
...config,
|
|
||||||
define: { 'process.env': {} },
|
|
||||||
resolve: {
|
|
||||||
alias: [
|
|
||||||
{
|
|
||||||
find: 'ui',
|
|
||||||
replacement: resolve(__dirname, '../../../packages/ui/'),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
docs: {
|
|
||||||
autodocs: true,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
export default config;
|
|
||||||
@@ -4,30 +4,25 @@
|
|||||||
"type": "module",
|
"type": "module",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "storybook dev -p 6006",
|
"dev": "vitepress dev src --port 6060",
|
||||||
"build": "storybook build --docs",
|
"build": "vitepress build src",
|
||||||
"preview-storybook": "serve storybook-static",
|
"serve": "vitepress serve src --port 6060",
|
||||||
"clean": "rm -rf .turbo node_modules",
|
"clean": "rm -rf .turbo node_modules src/.vitepress/dist src/.vitepress/cache"
|
||||||
"lint": "eslint ./stories/*.stories.tsx --max-warnings 0"
|
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@repo/ui": "workspace:*",
|
"@repo/ui": "workspace:*",
|
||||||
|
"dayjs": "^1.11.19",
|
||||||
"react": "^19.2.3",
|
"react": "^19.2.3",
|
||||||
"react-dom": "^19.2.3"
|
"react-dom": "^19.2.3"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@repo/eslint-config": "workspace:*",
|
"@repo/eslint-config": "workspace:*",
|
||||||
"@repo/typescript-config": "workspace:*",
|
"@repo/typescript-config": "workspace:*",
|
||||||
"@storybook/addon-actions": "^8.2.6",
|
|
||||||
"@storybook/addon-essentials": "^8.2.6",
|
|
||||||
"@storybook/addon-links": "^8.2.6",
|
|
||||||
"@storybook/react": "^8.2.6",
|
|
||||||
"@storybook/react-vite": "^8.2.6",
|
|
||||||
"@vitejs/plugin-react": "^5.1.2",
|
|
||||||
"eslint": "^8.57.0",
|
"eslint": "^8.57.0",
|
||||||
"serve": "^14.2.1",
|
"mermaid": "^11.15.0",
|
||||||
"storybook": "^8.2.6",
|
|
||||||
"typescript": "5.5.4",
|
"typescript": "5.5.4",
|
||||||
"vite": "^5.1.4"
|
"vitepress": "^1.6.4",
|
||||||
|
"vitepress-plugin-mermaid": "^2.0.17",
|
||||||
|
"vue": "^3.5.38"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,95 @@
|
|||||||
|
import { defineConfig } from 'vitepress'
|
||||||
|
import { withMermaid } from 'vitepress-plugin-mermaid'
|
||||||
|
|
||||||
|
const config = withMermaid(
|
||||||
|
defineConfig({
|
||||||
|
// title: "Frontend Monorepo",
|
||||||
|
title: 'Frontend Arch',
|
||||||
|
description: "Centralized documentation for the Enterprise Frontend Monorepo",
|
||||||
|
head: [
|
||||||
|
['link', { rel: 'icon', href: '/favicon.svg' }] // Jika Anda menggunakan favicon.svg
|
||||||
|
],
|
||||||
|
themeConfig: {
|
||||||
|
logo: '/logo.svg',
|
||||||
|
nav: [
|
||||||
|
{ text: 'Docs', link: '/overview' },
|
||||||
|
],
|
||||||
|
|
||||||
|
sidebar: [
|
||||||
|
{
|
||||||
|
text: 'Getting Started',
|
||||||
|
items: [
|
||||||
|
{ text: 'Project Overview', link: '/overview' },
|
||||||
|
{ text: 'Development Setup', link: '/setup' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: 'Core Architecture',
|
||||||
|
collapsed: false,
|
||||||
|
items: [
|
||||||
|
{ text: 'API & Domain Logic', link: '/packages/core-api/' },
|
||||||
|
{ text: 'Event Bus System', link: '/packages/core-events/' },
|
||||||
|
{ text: 'Storage & Persistence', link: '/packages/core-storage/' },
|
||||||
|
{ text: 'I18n & Localization', link: '/packages/core-i18n/' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: 'UI System',
|
||||||
|
collapsed: false,
|
||||||
|
items: [
|
||||||
|
{ text: 'Overview', link: '/packages/ui/' },
|
||||||
|
{ text: 'App Layout', link: '/packages/ui/CORE-APP-SHELL' },
|
||||||
|
{ text: 'Form Primitives', link: '/packages/ui/FORM-COMPONENTS' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: 'Desktop Ecosystem',
|
||||||
|
collapsed: false,
|
||||||
|
items: [
|
||||||
|
{ text: 'Overview', link: '/apps/desktop/' },
|
||||||
|
{ text: 'Lifecycle & Configuration', link: '/apps/desktop/CONFIGURATION' },
|
||||||
|
{ text: 'IPC & Bridge Architecture', link: '/apps/desktop/IPC_ARCHITECTURE' },
|
||||||
|
{ text: 'Distribution & Auto-Update', link: '/apps/desktop/AUTO_UPDATER' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
|
||||||
|
outline: { level: [2, 3] },
|
||||||
|
socialLinks: [
|
||||||
|
{
|
||||||
|
icon: {
|
||||||
|
svg: '<svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" height="24" width="24"><title>Gitea</title><path d="M4.209 4.603c-0.247 0 -0.525 0.02 -0.84 0.088 -0.333 0.07 -1.28 0.283 -2.054 1.027C-0.403 7.25 0.035 9.685 0.089 10.052c0.065 0.446 0.263 1.687 1.21 2.768 1.749 2.141 5.513 2.092 5.513 2.092s0.462 1.103 1.168 2.119c0.955 1.263 1.936 2.248 2.89 2.367 2.406 0 7.212 -0.004 7.212 -0.004s0.458 0.004 1.08 -0.394c0.535 -0.324 1.013 -0.893 1.013 -0.893s0.492 -0.527 1.18 -1.73c0.21 -0.37 0.385 -0.729 0.538 -1.068 0 0 2.107 -4.471 2.107 -8.823 -0.042 -1.318 -0.367 -1.55 -0.443 -1.627 -0.156 -0.156 -0.366 -0.153 -0.366 -0.153s-4.475 0.252 -6.792 0.306c-0.508 0.011 -1.012 0.023 -1.512 0.027v4.474l-0.634 -0.301c0 -1.39 -0.004 -4.17 -0.004 -4.17 -1.107 0.016 -3.405 -0.084 -3.405 -0.084s-5.399 -0.27 -5.987 -0.324c-0.187 -0.011 -0.401 -0.032 -0.648 -0.032zm0.354 1.832h0.111s0.271 2.269 0.6 3.597C5.549 11.147 6.22 13 6.22 13s-0.996 -0.119 -1.641 -0.348c-0.99 -0.324 -1.409 -0.714 -1.409 -0.714s-0.73 -0.511 -1.096 -1.52C1.444 8.73 2.021 7.7 2.021 7.7s0.32 -0.859 1.47 -1.145c0.395 -0.106 0.863 -0.12 1.072 -0.12zm8.33 2.554c0.26 0.003 0.509 0.127 0.509 0.127l0.868 0.422 -0.529 1.075a0.686 0.686 0 0 0 -0.614 0.359 0.685 0.685 0 0 0 0.072 0.756l-0.939 1.924a0.69 0.69 0 0 0 -0.66 0.527 0.687 0.687 0 0 0 0.347 0.763 0.686 0.686 0 0 0 0.867 -0.206 0.688 0.688 0 0 0 -0.069 -0.882l0.916 -1.874a0.667 0.667 0 0 0 0.237 -0.02 0.657 0.657 0 0 0 0.271 -0.137 8.826 8.826 0 0 1 1.016 0.512 0.761 0.761 0 0 1 0.286 0.282c0.073 0.21 -0.073 0.569 -0.073 0.569 -0.087 0.29 -0.702 1.55 -0.702 1.55a0.692 0.692 0 0 0 -0.676 0.477 0.681 0.681 0 1 0 1.157 -0.252c0.073 -0.141 0.141 -0.282 0.214 -0.431 0.19 -0.397 0.515 -1.16 0.515 -1.16 0.035 -0.066 0.218 -0.394 0.103 -0.814 -0.095 -0.435 -0.48 -0.638 -0.48 -0.638 -0.467 -0.301 -1.116 -0.58 -1.116 -0.58s0 -0.156 -0.042 -0.27a0.688 0.688 0 0 0 -0.148 -0.241l0.516 -1.062 2.89 1.401s0.48 0.218 0.583 0.619c0.073 0.282 -0.019 0.534 -0.069 0.657 -0.24 0.587 -2.1 4.317 -2.1 4.317s-0.232 0.554 -0.748 0.588a1.065 1.065 0 0 1 -0.393 -0.045l-0.202 -0.08 -4.31 -2.1s-0.417 -0.218 -0.49 -0.596c-0.083 -0.31 0.104 -0.691 0.104 -0.691l2.073 -4.272s0.183 -0.37 0.466 -0.497a0.855 0.855 0 0 1 0.35 -0.077z" fill="currentColor" stroke-width="1"></path></svg>'
|
||||||
|
},
|
||||||
|
link: 'https://git.eigen.co.id/eigen/fe-monorepo-template'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
|
||||||
|
// Mermaid configuration
|
||||||
|
mermaid: {
|
||||||
|
theme: 'default',
|
||||||
|
},
|
||||||
|
|
||||||
|
// Fix cascading CJS/ESM SyntaxErrors caused by Vite dynamically discovering mermaid
|
||||||
|
vite: {
|
||||||
|
optimizeDeps: {
|
||||||
|
include: [
|
||||||
|
'mermaid'
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
// Pnpm strict workspace workaround:
|
||||||
|
// vitepress-plugin-mermaid aggressively injects sub-dependencies into optimizeDeps.include.
|
||||||
|
// Because pnpm uses strict symlinks, Vite fails to resolve these sub-dependencies from the project root,
|
||||||
|
// causing pre-bundling to fail and cascading CJS/ESM SyntaxErrors in the browser.
|
||||||
|
// We strip them out so esbuild can naturally inline them into the 'mermaid' chunk instead.
|
||||||
|
if (config.vite?.optimizeDeps?.include) {
|
||||||
|
config.vite.optimizeDeps.include = config.vite.optimizeDeps.include.filter(
|
||||||
|
(dep) => !['@braintree/sanitize-url', 'debug', 'cytoscape-cose-bilkent', 'cytoscape'].includes(dep)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default config;
|
||||||
@@ -0,0 +1,80 @@
|
|||||||
|
/**
|
||||||
|
* VitePress Custom Theme CSS
|
||||||
|
* Applying brand color #652ed9 and its variants
|
||||||
|
*/
|
||||||
|
|
||||||
|
:root {
|
||||||
|
/* Brand color #652ed9 */
|
||||||
|
--vp-c-brand-1: #652ed9;
|
||||||
|
--vp-c-brand-2: #804aea;
|
||||||
|
--vp-c-brand-3: #9b6ff8;
|
||||||
|
--vp-c-brand-soft: rgba(101, 46, 217, 0.16);
|
||||||
|
|
||||||
|
/* Hover states */
|
||||||
|
--vp-button-brand-hover-bg: var(--vp-c-brand-2);
|
||||||
|
--vp-button-brand-hover-text: var(--vp-c-white);
|
||||||
|
--vp-button-brand-active-bg: var(--vp-c-brand-1);
|
||||||
|
|
||||||
|
/* Focus states */
|
||||||
|
--vp-custom-block-brand-border: var(--vp-c-brand-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark {
|
||||||
|
/* Slightly adjusted variants for dark mode, keeping the primary brand color consistent */
|
||||||
|
--vp-c-brand-1: #8a57f3;
|
||||||
|
--vp-c-brand-2: #7a42ec;
|
||||||
|
--vp-c-brand-3: #652ed9;
|
||||||
|
--vp-c-brand-soft: rgba(101, 46, 217, 0.25);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Sesuaikan ukuran logo di navbar */
|
||||||
|
/* .VPNavBar .logo {
|
||||||
|
height: 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.VPNavBar .VPNavBarTitle{
|
||||||
|
|
||||||
|
} */
|
||||||
|
|
||||||
|
/* ==========================================================================
|
||||||
|
OPTIMASI NAVBAR TITLE & LOGO (ELEGANT ALIGNMENT)
|
||||||
|
========================================================================== */
|
||||||
|
.VPNavBar .VPNavBarTitle {
|
||||||
|
display: flex;
|
||||||
|
align-items: center; /* Memastikan logo & teks sejajar sempurna secara vertikal */
|
||||||
|
gap: 12px; /* Spasi yang lebih longgar dan elegan antara logo & teks */
|
||||||
|
padding: 0 16px; /* Memberikan ruang napas di dalam kontainer title */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ==========================================================================
|
||||||
|
ELEGANT HARMONIOUS GRADIENT (Subtle Mode-Aware)
|
||||||
|
========================================================================== */
|
||||||
|
.VPNavBar .VPNavBarTitle .title {
|
||||||
|
/* LIGHT MODE: Gradien dari warna Brand gelap ke warna Brand terang */
|
||||||
|
/* Kita hindari hitam pekat, gunakan ungu yang lebih dalam */
|
||||||
|
background: linear-gradient(135deg, #4b23a6 0%, var(--vp-c-brand-1) 100%);
|
||||||
|
-webkit-background-clip: text;
|
||||||
|
-webkit-text-fill-color: transparent;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* DARK MODE: Gradien dari ungu sangat muda ke warna Brand */
|
||||||
|
.dark .VPNavBar .VPNavBarTitle .title {
|
||||||
|
/* Kita kurangi dominasi putih dengan menggunakan ungu yang sangat terang */
|
||||||
|
background: linear-gradient(135deg, #c5a8ff 30%, var(--vp-c-brand-1) 100%);
|
||||||
|
-webkit-background-clip: text;
|
||||||
|
-webkit-text-fill-color: transparent;
|
||||||
|
/* Glow diperhalus agar tidak terlalu menyilaukan */
|
||||||
|
filter: drop-shadow(0 0 8px rgba(101, 46, 217, 0.2));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Hover effect yang lebih kalem */
|
||||||
|
.VPNavBar .VPNavBarTitle .title:hover {
|
||||||
|
filter: drop-shadow(0 0 12px rgba(101, 46, 217, 0.4));
|
||||||
|
}
|
||||||
|
|
||||||
|
.VPNavBar .logo {
|
||||||
|
height: 28px; /* Menyeimbangkan ukuran logo dengan tinggi teks */
|
||||||
|
width: 28px;
|
||||||
|
margin-right: 0; /* Margin sudah digantikan oleh 'gap' pada parent */
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
import DefaultTheme from 'vitepress/theme'
|
||||||
|
import './custom.css'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
extends: DefaultTheme,
|
||||||
|
}
|
||||||
@@ -1,4 +1,3 @@
|
|||||||
[← Back to Root](../../../README.md)
|
|
||||||
|
|
||||||
# Desktop Auto-Update System
|
# Desktop Auto-Update System
|
||||||
|
|
||||||
@@ -110,7 +109,8 @@ pnpm run prebuild
|
|||||||
GH_TOKEN=your_token electron-builder --publish always --config electron-builder.yml
|
GH_TOKEN=your_token electron-builder --publish always --config electron-builder.yml
|
||||||
```
|
```
|
||||||
|
|
||||||
> [!CAUTION] > **Treat `GH_TOKEN` as a critical secret.** It grants write access to your repository's release assets. Never commit it to version control, never log it in CI output, and always inject it via encrypted secrets or a vault.
|
> [!CAUTION]
|
||||||
|
> **Treat `GH_TOKEN` as a critical secret.** It grants write access to your repository's release assets. Never commit it to version control, never log it in CI output, and always inject it via encrypted secrets or a vault.
|
||||||
|
|
||||||
### Automated Release (GitHub Actions)
|
### Automated Release (GitHub Actions)
|
||||||
|
|
||||||
@@ -172,7 +172,7 @@ jobs:
|
|||||||
|
|
||||||
1. Navigate to **Settings → Secrets and variables → Actions** in your GitHub repository.
|
1. Navigate to **Settings → Secrets and variables → Actions** in your GitHub repository.
|
||||||
2. Add each variable as a **Repository secret**.
|
2. Add each variable as a **Repository secret**.
|
||||||
3. Reference them in workflow files as `${{ secrets.VARIABLE_NAME }}`.
|
3. Reference them in workflow files as <code v-pre>${{ secrets.VARIABLE_NAME }}</code>.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -228,7 +228,8 @@ publish:
|
|||||||
|
|
||||||
Your server must host the same directory structure as the S3 layout above.
|
Your server must host the same directory structure as the S3 layout above.
|
||||||
|
|
||||||
> [!IMPORTANT] > **MIME Type Configuration**: Ensure your file server correctly serves `.yml` files with `text/yaml` and installer binaries with `application/octet-stream`. Incorrect MIME types will cause download corruption or silent update failures.
|
> [!IMPORTANT]
|
||||||
|
> **MIME Type Configuration**: Ensure your file server correctly serves `.yml` files with `text/yaml` and installer binaries with `application/octet-stream`. Incorrect MIME types will cause download corruption or silent update failures.
|
||||||
|
|
||||||
**Nginx reference:**
|
**Nginx reference:**
|
||||||
|
|
||||||
@@ -255,7 +256,8 @@ server {
|
|||||||
|
|
||||||
## 🛡️ Code Signing: The Trust Boundary
|
## 🛡️ Code Signing: The Trust Boundary
|
||||||
|
|
||||||
> [!WARNING] > **Code signing is not merely a requirement — it is the Trust Boundary established by the operating system.** macOS Gatekeeper will explicitly terminate unsigned applications or refuse background updates to maintain system integrity. Windows SmartScreen will display alarming warnings to users. Without valid signatures, `electron-updater` will **reject update payloads entirely**.
|
> [!WARNING]
|
||||||
|
> **Code signing is not merely a requirement — it is the Trust Boundary established by the operating system.** macOS Gatekeeper will explicitly terminate unsigned applications or refuse background updates to maintain system integrity. Windows SmartScreen will display alarming warnings to users. Without valid signatures, `electron-updater` will **reject update payloads entirely**.
|
||||||
|
|
||||||
### macOS
|
### macOS
|
||||||
|
|
||||||
@@ -1,4 +1,3 @@
|
|||||||
[← Back to Root](../../../README.md)
|
|
||||||
|
|
||||||
# Desktop Configuration Guide
|
# Desktop Configuration Guide
|
||||||
|
|
||||||
+16
-4
@@ -1,10 +1,21 @@
|
|||||||
[← Back to Root](../../../README.md)
|
---
|
||||||
|
outline: [2, 3]
|
||||||
|
---
|
||||||
|
|
||||||
# IPC Architecture & Security Model
|
# IPC Architecture & Security Model
|
||||||
|
|
||||||
The Secure Communication Blueprint.
|
> **Scope**: Electron Main ↔ Renderer process communication
|
||||||
|
> **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**, ensuring that the Node.js Main Process remains cryptographically and logically isolated from untrusted web content. Adherence to this document is **mandatory** — deviations constitute security violations subject to immediate remediation.
|
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.
|
||||||
|
|
||||||
|
The architecture operates on three invariants:
|
||||||
|
|
||||||
|
| Invariant | Guarantee |
|
||||||
|
|---|---|
|
||||||
|
| **Context Encapsulation** | The Preload Script executes in a hermetically sealed V8 context, isolated from both Main Process globals and the Renderer DOM. |
|
||||||
|
| **Interface Narrowing** | Only explicitly declared, type-safe API surfaces are exposed via `contextBridge`. No wildcard access patterns exist. |
|
||||||
|
| **Deterministic Lifecycle** | All IPC subscriptions are paired with unsubscribe functions, tying native event listeners to React's component lifecycle to prevent memory leaks. |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -96,7 +107,8 @@ These settings are declared in `BrowserWindow.webPreferences` and are **non-nego
|
|||||||
|
|
||||||
Every native feature in this architecture **must** follow the Three-Step Bridge — a Standard Operating Procedure (SOP) that ensures traceability, type-safety, and auditability across the entire IPC surface.
|
Every native feature in this architecture **must** follow the Three-Step Bridge — a Standard Operating Procedure (SOP) that ensures traceability, type-safety, and auditability across the entire IPC surface.
|
||||||
|
|
||||||
> [!IMPORTANT] > **Deterministic Synchronization**: Maintaining parity between the Main Process handler, the Preload Gateway exposure, and the TypeScript interface declaration is **mandatory**. A mismatch between any two of the three layers will result in either a **Type-Safety Gap** (silent failures in development) or a **Runtime Regression** (crashes in production).
|
> [!IMPORTANT]
|
||||||
|
> **Deterministic Synchronization**: Maintaining parity between the Main Process handler, the Preload Gateway exposure, and the TypeScript interface declaration is **mandatory**. A mismatch between any two of the three layers will result in either a **Type-Safety Gap** (silent failures in development) or a **Runtime Regression** (crashes in production).
|
||||||
|
|
||||||
### Step 1: Register the Handler — Main Process
|
### Step 1: Register the Handler — Main Process
|
||||||
|
|
||||||
@@ -102,7 +102,7 @@ All artifacts are emitted to the `release/` directory.
|
|||||||
> APPLE_APP_SPECIFIC_PASSWORD=<app-specific password>
|
> APPLE_APP_SPECIFIC_PASSWORD=<app-specific password>
|
||||||
> APPLE_TEAM_ID=<team id>
|
> APPLE_TEAM_ID=<team id>
|
||||||
> ```
|
> ```
|
||||||
> Without valid code signing, macOS Gatekeeper will quarantine the application and `electron-updater` will reject update payloads. See [docs/AUTO_UPDATER.md](docs/AUTO_UPDATER.md) for the complete requirements.
|
> Without valid code signing, macOS Gatekeeper will quarantine the application and `electron-updater` will reject update payloads. See [AUTO_UPDATER.md](./AUTO_UPDATER.md) for the complete requirements.
|
||||||
|
|
||||||
> [!NOTE]
|
> [!NOTE]
|
||||||
> **Cross-Compilation Advisory**: It is strongly recommended to build for each platform on its native OS. Cross-compilation (e.g., producing `.dmg` on Linux) may fail due to platform-specific toolchain dependencies. For CI, leverage a matrix strategy:
|
> **Cross-Compilation Advisory**: It is strongly recommended to build for each platform on its native OS. Cross-compilation (e.g., producing `.dmg` on Linux) may fail due to platform-specific toolchain dependencies. For CI, leverage a matrix strategy:
|
||||||
@@ -124,7 +124,7 @@ DESKTOP_TARGET_APP=web
|
|||||||
DESKTOP_DEV_SERVER_URL=http://localhost:5173
|
DESKTOP_DEV_SERVER_URL=http://localhost:5173
|
||||||
```
|
```
|
||||||
|
|
||||||
See [docs/CONFIGURATION.md](docs/CONFIGURATION.md) for comprehensive guidance on target app switching, protocol internals, and the HashRouter fallback procedure.
|
See [CONFIGURATION.md](./CONFIGURATION.md) for comprehensive guidance on target app switching, protocol internals, and the HashRouter fallback procedure.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -140,7 +140,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 [docs/AUTO_UPDATER.md](docs/AUTO_UPDATER.md).
|
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).
|
||||||
|
|
||||||
### 🛡️ CORS Bypass Proxy
|
### 🛡️ CORS Bypass Proxy
|
||||||
|
|
||||||
@@ -173,7 +173,7 @@ The Desktop Wrapper enforces a **hardened security perimeter**, strictly isolati
|
|||||||
- **Origin Sanitization** — `session.defaultSession.webRequest` intercepts all outgoing requests, stripping `app://` / `file://` Origin headers to prevent backend CORS rejections.
|
- **Origin Sanitization** — `session.defaultSession.webRequest` intercepts all outgoing requests, stripping `app://` / `file://` Origin headers to prevent backend CORS rejections.
|
||||||
- **Navigation Guard** — The `will-navigate` event intercepts and blocks all navigation attempts to URLs outside the `app://` protocol and the authorized dev server origin.
|
- **Navigation Guard** — The `will-navigate` event intercepts and blocks all navigation attempts to URLs outside the `app://` protocol and the authorized dev server origin.
|
||||||
|
|
||||||
See [docs/IPC_ARCHITECTURE.md](docs/IPC_ARCHITECTURE.md) for the full security model, the Three-Step Bridge pattern, and guidance on safely extending the app with new native features.
|
See [IPC_ARCHITECTURE.md](./IPC_ARCHITECTURE.md) for the full security model, the Three-Step Bridge pattern, and guidance on safely extending the app with new native features.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -181,6 +181,6 @@ See [docs/IPC_ARCHITECTURE.md](docs/IPC_ARCHITECTURE.md) for the full security m
|
|||||||
|
|
||||||
| Document | Scope |
|
| Document | Scope |
|
||||||
|---|---|
|
|---|---|
|
||||||
| [CONFIGURATION.md](docs/CONFIGURATION.md) | Target app switching, `app://` protocol internals, HashRouter fallback procedure |
|
| [CONFIGURATION.md](./CONFIGURATION.md) | Target app switching, `app://` protocol internals, HashRouter fallback procedure |
|
||||||
| [AUTO_UPDATER.md](docs/AUTO_UPDATER.md) | Release lifecycle, CI/CD variables, provider switching, code signing |
|
| [AUTO_UPDATER.md](./AUTO_UPDATER.md) | Release lifecycle, CI/CD variables, provider switching, code signing |
|
||||||
| [IPC_ARCHITECTURE.md](docs/IPC_ARCHITECTURE.md) | Security model, Three-Step Bridge pattern, existing IPC channels, extensibility guide |
|
| [IPC_ARCHITECTURE.md](./IPC_ARCHITECTURE.md) | Security model, Three-Step Bridge pattern, existing IPC channels, extensibility guide |
|
||||||
@@ -0,0 +1,265 @@
|
|||||||
|
---
|
||||||
|
layout: home
|
||||||
|
|
||||||
|
hero:
|
||||||
|
name: "Frontend Architecture"
|
||||||
|
text: "Enterprise Monorepo"
|
||||||
|
tagline: "A scalable, standardized foundation for Web & Desktop applications. Built for performance, consistency, and velocity."
|
||||||
|
actions:
|
||||||
|
- theme: brand
|
||||||
|
text: Get Started
|
||||||
|
link: /setup
|
||||||
|
- theme: alt
|
||||||
|
text: View Architecture
|
||||||
|
link: /overview
|
||||||
|
|
||||||
|
features:
|
||||||
|
- title: 🧩 App Layout Engine
|
||||||
|
details: Core App Shell wrapping Mantine for rapid, consistent layout creation across all products.
|
||||||
|
link: /packages/ui/CORE-APP-SHELL
|
||||||
|
linkText: Explore App Shell
|
||||||
|
- title: 📝 Form Primitives
|
||||||
|
details: RHF + Zod + Mantine components designed for O(1) render cost and deep type safety.
|
||||||
|
link: /packages/ui/FORM-COMPONENTS
|
||||||
|
linkText: View Forms
|
||||||
|
- title: 🖥️ Desktop Ecosystem
|
||||||
|
details: Complete Electron integration with secure Inter-Process Communication (IPC) and Bridge Architecture.
|
||||||
|
link: /apps/desktop/
|
||||||
|
linkText: Desktop Docs
|
||||||
|
- title: 🔌 Core Architecture
|
||||||
|
details: Robust state management, Event Bus, first-class i18n, and unified Storage layers.
|
||||||
|
link: /packages/core-api/
|
||||||
|
linkText: Explore Core
|
||||||
|
---
|
||||||
|
<div class="custom-divider"></div>
|
||||||
|
<div class="bento-container">
|
||||||
|
<div class="bento-header">
|
||||||
|
<h2>Why this Monorepo Exists</h2>
|
||||||
|
<p>Building high-end enterprise applications requires strict consistency, shared tooling, and well-defined boundaries. This monorepo serves as the absolute source of truth for our frontend ecosystem.</p>
|
||||||
|
</div>
|
||||||
|
<div class="bento-grid">
|
||||||
|
<div class="bento-card">
|
||||||
|
<div class="bento-icon">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.77-3.77a6 6 0 0 1-7.94 7.94l-6.91 6.91a2.12 2.12 0 0 1-3-3l6.91-6.91a6 6 0 0 1 7.94-7.94l-3.76 3.76z"></path></svg>
|
||||||
|
</div>
|
||||||
|
<h3>Unified Tooling</h3>
|
||||||
|
<p>By enforcing strict linting, formatting, and building patterns at the root (powered by Turborepo), we ensure that every application in the ecosystem adheres to our high standards without duplicate configuration.</p>
|
||||||
|
</div>
|
||||||
|
<div class="bento-card">
|
||||||
|
<div class="bento-icon">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z"></path><polyline points="3.27 6.96 12 12.01 20.73 6.96"></polyline><line x1="12" y1="22.08" x2="12" y2="12"></line></svg>
|
||||||
|
</div>
|
||||||
|
<h3>Shared Domain Logic</h3>
|
||||||
|
<p>The separation of UI components and Core logic guarantees that our web and desktop applications all share the exact same state management and event-driven architecture, drastically reducing cognitive load.</p>
|
||||||
|
</div>
|
||||||
|
<div class="bento-card">
|
||||||
|
<div class="bento-icon">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2"></polygon></svg>
|
||||||
|
</div>
|
||||||
|
<h3>Accelerated Velocity</h3>
|
||||||
|
<p>With a rich library of 22+ advanced Form components, pre-configured Vite/TypeScript environments, and an enterprise App Shell, teams can stop reinventing the wheel and start building product features on day one.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
/* ==========================================================================
|
||||||
|
SECTION 1: GLOBAL & HERO BACKGROUNDS (Masked Dot Grid & Top Glow)
|
||||||
|
========================================================================== */
|
||||||
|
:global(.VPHome) {
|
||||||
|
position: relative;
|
||||||
|
z-index: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Efek Brand Glow memancar halus dari atas tengah (Area Hero) */
|
||||||
|
:global(.VPHome::before) {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 50%;
|
||||||
|
transform: translateX(-50%);
|
||||||
|
width: 100vw;
|
||||||
|
max-width: 1200px;
|
||||||
|
height: 800px;
|
||||||
|
background: radial-gradient(ellipse at top, var(--vp-c-brand-soft) 0%, transparent 70%);
|
||||||
|
filter: blur(100px);
|
||||||
|
z-index: -1;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Efek Dot Grid yang dibatasi hanya setinggi Hero dan memudar ke bawah */
|
||||||
|
:global(.VPHome::after) {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 600px;
|
||||||
|
background-image: radial-gradient(var(--vp-c-divider) 1px, transparent 1px);
|
||||||
|
background-size: 24px 24px;
|
||||||
|
background-position: top center;
|
||||||
|
z-index: -2;
|
||||||
|
pointer-events: none;
|
||||||
|
-webkit-mask-image: linear-gradient(to bottom, black 40%, transparent 100%);
|
||||||
|
mask-image: linear-gradient(to bottom, black 40%, transparent 100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ==========================================================================
|
||||||
|
SECTION 2: BENTO CONTAINER & HEADER (Structured Minimalism)
|
||||||
|
========================================================================== */
|
||||||
|
/* Divider dengan jarak vertikal yang presisi dan lega */
|
||||||
|
.custom-divider {
|
||||||
|
width: 100%;
|
||||||
|
height: 1px;
|
||||||
|
background-color: var(--vp-c-divider);
|
||||||
|
margin: 80px 0 64px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bento-container {
|
||||||
|
max-width: 1152px;
|
||||||
|
margin: auto;
|
||||||
|
padding: 0 24px;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bento-header {
|
||||||
|
text-align: center;
|
||||||
|
margin-bottom: 64px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bento-header h2 {
|
||||||
|
font-size: 2.5em;
|
||||||
|
font-weight: 700;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
color: var(--vp-c-text-1);
|
||||||
|
letter-spacing: -0.02em;
|
||||||
|
line-height: 1.2;
|
||||||
|
border-top: none;
|
||||||
|
padding-top: 0;
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bento-header p {
|
||||||
|
font-size: 1.15em;
|
||||||
|
color: var(--vp-c-text-2);
|
||||||
|
max-width: 760px; /* Memaksa teks membungkus menjadi 2 baris yang ideal */
|
||||||
|
margin: 0 auto;
|
||||||
|
line-height: 1.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ==========================================================================
|
||||||
|
SECTION 2: BENTO GRID & CARD DESIGN (Premium Glassmorphism)
|
||||||
|
========================================================================== */
|
||||||
|
.bento-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
|
||||||
|
gap: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bento-card {
|
||||||
|
background: var(--vp-c-bg-soft);
|
||||||
|
backdrop-filter: blur(8px);
|
||||||
|
-webkit-backdrop-filter: blur(8px);
|
||||||
|
border: 1px solid var(--vp-c-divider); /* Border solid yang tipis dan bersih */
|
||||||
|
border-radius: 16px;
|
||||||
|
padding: 40px 32px; /* Spacing dalam yang luas memberikan kesan premium */
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-start;
|
||||||
|
/* Transisi mulus untuk pergerakan, border, dan bayangan */
|
||||||
|
transition: transform 0.4s cubic-bezier(0.25, 1, 0.5, 1),
|
||||||
|
border-color 0.4s ease,
|
||||||
|
box-shadow 0.4s ease;
|
||||||
|
|
||||||
|
/* Perubahan Utama: Bayangan statis yang sangat halus (elegan, tidak berisik) */
|
||||||
|
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
|
||||||
|
|
||||||
|
/* Transisi hover yang lebih lembut dan "mahal" */
|
||||||
|
transition: all 0.5s cubic-bezier(0.165, 0.84, 0.44, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Interaksi hover kartu: Terangkat sedikit dengan pendaran tipis warna brand */
|
||||||
|
.bento-card:hover {
|
||||||
|
/* Elevasi yang lebih tinggi saat di-hover */
|
||||||
|
transform: translateY(-8px);
|
||||||
|
|
||||||
|
/* Shadow saat hover: Warna brand dengan opasitas sangat rendah agar tetap profesional */
|
||||||
|
box-shadow: 0 20px 25px -5px rgba(101, 46, 217, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
|
||||||
|
|
||||||
|
/* Border sedikit lebih terang */
|
||||||
|
border-color: var(--vp-c-brand-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.bento-icon {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: 48px;
|
||||||
|
height: 48px;
|
||||||
|
border-radius: 12px;
|
||||||
|
background: var(--vp-c-bg-mute);
|
||||||
|
color: var(--vp-c-brand-1);
|
||||||
|
margin-bottom: 24px;
|
||||||
|
transition: background 0.3s ease, color 0.3s ease, transform 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bento-icon svg {
|
||||||
|
width: 24px;
|
||||||
|
height: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Interaksi hover ikon: Mengisi warna latar dengan warna brand */
|
||||||
|
.bento-card:hover .bento-icon {
|
||||||
|
background: var(--vp-c-brand-1);
|
||||||
|
color: #ffffff;
|
||||||
|
transform: scale(1.05);
|
||||||
|
}
|
||||||
|
|
||||||
|
.bento-card h3 {
|
||||||
|
font-size: 1.3em;
|
||||||
|
font-weight: 600;
|
||||||
|
color: var(--vp-c-text-1);
|
||||||
|
margin-top: 0;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bento-card p {
|
||||||
|
font-size: 1em;
|
||||||
|
color: var(--vp-c-text-2);
|
||||||
|
line-height: 1.6;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ==========================================================================
|
||||||
|
9. MEDIA QUERIES (Responsive Adaptations)
|
||||||
|
========================================================================== */
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.custom-divider {
|
||||||
|
margin: 48px 0;
|
||||||
|
}
|
||||||
|
.bento-header {
|
||||||
|
margin-bottom: 48px;
|
||||||
|
}
|
||||||
|
.bento-header h2 {
|
||||||
|
font-size: 2em;
|
||||||
|
}
|
||||||
|
.bento-header p {
|
||||||
|
font-size: 1.05em;
|
||||||
|
}
|
||||||
|
.bento-card {
|
||||||
|
padding: 32px 24px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 480px) {
|
||||||
|
.bento-grid {
|
||||||
|
grid-template-columns: 1fr; /* Menjadi satu kolom penuh pada ponsel kecil */
|
||||||
|
}
|
||||||
|
.bento-card {
|
||||||
|
padding: 24px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,169 @@
|
|||||||
|
# Monorepo Architecture Overview
|
||||||
|
|
||||||
|
## 📂 Repository Structure
|
||||||
|
|
||||||
|
The monorepo is organized into **Apps** (deployable applications) and **Packages** (shared libraries).
|
||||||
|
|
||||||
|
```text
|
||||||
|
.
|
||||||
|
├── apps/
|
||||||
|
│ ├── web/ # Main React Application (Vite + TypeScript)
|
||||||
|
│ ├── landing/ # Public Promotional SPA (Vite + TypeScript)
|
||||||
|
│ ├── desktop/ # Electron Desktop Wrapper (electron-vite)
|
||||||
|
│ └── docs-dev/ # Component Documentation & Playground (VitePress)
|
||||||
|
│
|
||||||
|
├── packages/
|
||||||
|
│ ├── core-api/ # Shared HTTP Client, Observability & Data Services Engine
|
||||||
|
│ ├── core-storage/ # Enterprise Storage Engine (IndexedDB/localStorage + Encryption)
|
||||||
|
│ ├── core-i18n/ # Enterprise Internationalization Architecture
|
||||||
|
│ ├── ui/ # Shared UI Component Library
|
||||||
|
│ ├── utils/ # Shared Utilities (Date, Encryption, Core Logic, etc)
|
||||||
|
│ └── configs/ # Shared Tooling Configurations
|
||||||
|
│ ├── eslint/ # Shared ESLint rules
|
||||||
|
│ └── typescript/ # Shared TypeScript (tsconfig) bases
|
||||||
|
│
|
||||||
|
├── package.json # Root scripts and dependencies
|
||||||
|
├── pnpm-workspace.yaml # pnpm workspace definition
|
||||||
|
└── turbo.json # Turborepo pipeline configuration
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📦 Packages Overview
|
||||||
|
|
||||||
|
### 1. `apps/web`
|
||||||
|
The main consumer-facing application.
|
||||||
|
|
||||||
|
* Imports business logic from `@repo/utils`
|
||||||
|
* Uses shared UI components from `@repo/ui`
|
||||||
|
|
||||||
|
**Tech Stack**:
|
||||||
|
|
||||||
|
* React
|
||||||
|
* Vite
|
||||||
|
* TypeScript
|
||||||
|
* Tailwind CSS
|
||||||
|
|
||||||
|
### 2. `apps/desktop`
|
||||||
|
The **Electron desktop wrapper** that embeds `apps/web` for native desktop experiences.
|
||||||
|
|
||||||
|
* In **development**: loads the Vite dev server with full hot reload
|
||||||
|
* In **production**: serves the static web build via a secure custom `app://` protocol
|
||||||
|
* Configurable target app via `.env` (can wrap `apps/web`, `apps/docs-dev`, or any future app)
|
||||||
|
|
||||||
|
**Tech Stack**:
|
||||||
|
|
||||||
|
* Electron 33.x
|
||||||
|
* electron-vite
|
||||||
|
* electron-builder
|
||||||
|
* electron-updater
|
||||||
|
|
||||||
|
**Key Capabilities**:
|
||||||
|
|
||||||
|
| Feature | Description |
|
||||||
|
|---|---|
|
||||||
|
| 🖨️ Native Printing | Silent and direct printing via secure IPC bridge |
|
||||||
|
| 🔄 Auto-Updates | Background downloads via GitHub Releases (switchable to S3) |
|
||||||
|
| 🔒 Secure IPC Bridge | `contextIsolation: true`, `nodeIntegration: false`, `sandbox: true` |
|
||||||
|
| 🌐 Custom Protocol | `app://` serves static files with SPA routing fallback to `index.html` |
|
||||||
|
| 🛡️ CORS Bypass | Transparent Origin header rewriting for cloud API calls |
|
||||||
|
|
||||||
|
### 3. `apps/landing`
|
||||||
|
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
|
||||||
|
* 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
|
||||||
|
|
||||||
|
**Tech Stack**:
|
||||||
|
|
||||||
|
* React
|
||||||
|
* Vite
|
||||||
|
* TypeScript
|
||||||
|
* Tailwind CSS v4
|
||||||
|
|
||||||
|
### 4. `apps/docs-dev`
|
||||||
|
An isolated environment for developing and documenting UI components.
|
||||||
|
* Ensures components in `@repo/ui` are built and tested independently
|
||||||
|
* Acts as a living design system and playground
|
||||||
|
* Built with **VitePress**
|
||||||
|
|
||||||
|
### 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.
|
||||||
|
|
||||||
|
* Consumed by `apps/web`, `apps/landing`, and any future workspace
|
||||||
|
* Centralizes all `@grafana/faro-*` and `@opentelemetry/*` dependencies
|
||||||
|
* Provides plug-and-play telemetry via `initTelemetry()` + `faroAdapter`
|
||||||
|
|
||||||
|
**Tech Stack**:
|
||||||
|
|
||||||
|
* Axios (isolated instances, zero singleton pollution)
|
||||||
|
* Grafana Faro (RUM, Logs, Error tracking)
|
||||||
|
* OpenTelemetry (custom spans, distributed tracing)
|
||||||
|
* TypeScript (strict types, module augmentation)
|
||||||
|
|
||||||
|
**Key Capabilities**:
|
||||||
|
|
||||||
|
| Feature | Description |
|
||||||
|
|---|---|
|
||||||
|
| 🏭 HTTP Client Factory | `createHttpClient()` — per-app isolated Axios instances with interceptor hooks |
|
||||||
|
| 📡 Faro/Loki Baseline | Every request automatically pushes structured logs with `module.key` and `module.action` |
|
||||||
|
| 🎯 Custom Spans (Opt-In) | `telemetryContext.customSpanName` creates explicit OTel spans visible in Grafana Tempo |
|
||||||
|
| 🛡️ Error Normalization | `ApiError.fromAxiosError()` — structured, serializable error codes for all failure modes |
|
||||||
|
| 📦 Data Services Engine | `CommonRemoteDataServices` — full CRUD + lifecycle operations with zero boilerplate |
|
||||||
|
|
||||||
|
### 6. `packages/core-storage`
|
||||||
|
The **Enterprise-grade storage engine** for the monorepo.
|
||||||
|
Provides a unified, Promise-based interface for interacting with browser storage (`localStorage` and `IndexedDB`). Enforces strict type safety, prevents key collisions via a centralized registry, and automatically provides **AES encryption at rest** for sensitive payloads using `@repo/utils`.
|
||||||
|
|
||||||
|
### 7. `packages/core-i18n`
|
||||||
|
The **Enterprise Internationalization Architecture** for the monorepo.
|
||||||
|
|
||||||
|
Provides a Hybrid Namespace Architecture combining a centralized i18n engine with decentralized, lazy-loaded feature dictionaries. Features strict TypeScript typings (including nested keys), optional backend synchronization with automatic error rollbacks, and a deep-merge mechanism for dynamic tenant-specific vocabulary overrides.
|
||||||
|
|
||||||
|
**Key Capabilities**:
|
||||||
|
|
||||||
|
| Feature | Description |
|
||||||
|
|---|---|
|
||||||
|
| 🌐 Hybrid Namespaces | Centralized `common` corpus + lazy-loaded feature dictionaries. |
|
||||||
|
| 🛡️ Strict Typings | Native TS autocomplete for nested paths (e.g., `header.title`) via module augmentation. |
|
||||||
|
| 🔄 Safe Backend Sync | `changeLanguage` accepts a `syncCallback` with built-in rollback if the API fails. |
|
||||||
|
| 🏢 Tenant Overrides | `applyTenantOverrides` performs a partial deep-merge to selectively override terminology. |
|
||||||
|
|
||||||
|
### 8. `packages/core-events`
|
||||||
|
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.
|
||||||
|
|
||||||
|
**Key Capabilities**:
|
||||||
|
|
||||||
|
| Feature | Description |
|
||||||
|
|---|---|
|
||||||
|
| 🧩 Zero Coupling | Publishers and subscribers interact via blind events, eliminating direct module imports and circular dependencies. |
|
||||||
|
| ⚡ Extreme Performance | Enables targeted DOM updates for high-frequency data streams (e.g., WebSockets) without re-rendering parent components. |
|
||||||
|
| 🧹 Memory Safety | Native `useAppEvent` hook automatically unsubscribes on component unmount, preventing SPA memory leaks. |
|
||||||
|
| 🛡️ Strict Contracts | Centralized `events.registry.ts` enforces payload shapes via TypeScript, ensuring cross-module data safety. |
|
||||||
|
|
||||||
|
### 9. `packages/utils`
|
||||||
|
Shared business logic and reusable utility modules that can be consumed across multiple applications. Fully tested using Vitest.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
### 10. `packages/ui`
|
||||||
|
Shared UI component library (Buttons, Inputs, Cards, Layouts) with a comprehensive **Form UI Library**.
|
||||||
|
|
||||||
|
* Ensures consistent design across all applications
|
||||||
|
* 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
|
||||||
|
|
||||||
|
### 11. `packages/configs`
|
||||||
|
Single source of truth for tooling configuration.
|
||||||
|
* **eslint-config**: Shared ESLint rules
|
||||||
|
* **typescript-config**: Shared `tsconfig.json` base configurations
|
||||||
|
|
||||||
|
## ⚙️ Configuration & Environment
|
||||||
|
|
||||||
|
### Turborepo Caching
|
||||||
|
This repository uses **Turborepo caching** for builds, tests, and other artifacts.
|
||||||
|
To fully clean the workspace (dependencies, build outputs, and Turbo cache):
|
||||||
|
```bash
|
||||||
|
rm -rf node_modules **/*/node_modules .turbo **/*/.turbo dist **/*/dist out **/*/out web-dist **/*/web-dist release **/*/release
|
||||||
|
```
|
||||||
@@ -1,4 +1,3 @@
|
|||||||
[← Back to Root](../../README.md)
|
|
||||||
|
|
||||||
# Enterprise API Engine (`@repo/core-api`)
|
# Enterprise API Engine (`@repo/core-api`)
|
||||||
|
|
||||||
@@ -1,4 +1,3 @@
|
|||||||
[← Back to Root](../../README.md)
|
|
||||||
|
|
||||||
# Event Bus (`@repo/core-events`)
|
# Event Bus (`@repo/core-events`)
|
||||||
|
|
||||||
@@ -1,4 +1,3 @@
|
|||||||
[← Back to Root](../../README.md)
|
|
||||||
|
|
||||||
# i18n Architecture (`@repo/core-i18n`)
|
# i18n Architecture (`@repo/core-i18n`)
|
||||||
|
|
||||||
@@ -1,4 +1,3 @@
|
|||||||
[← Back to Root](../../README.md)
|
|
||||||
|
|
||||||
# Storage Engine (`@repo/core-storage`)
|
# Storage Engine (`@repo/core-storage`)
|
||||||
|
|
||||||
+6
-2
@@ -1,4 +1,8 @@
|
|||||||
# Core App Shell — Layout Engine Architecture & Usage Guide
|
---
|
||||||
|
outline: [2, 3]
|
||||||
|
---
|
||||||
|
|
||||||
|
# Core App Shell — Layout Engine
|
||||||
|
|
||||||
> **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 (`AppShell`), `@mantine/hooks`
|
||||||
@@ -74,7 +78,7 @@ packages/ui/src/components/core-app-shell/
|
|||||||
└── index.ts # Barrel exports
|
└── index.ts # Barrel exports
|
||||||
```
|
```
|
||||||
|
|
||||||
**Source**: [`core-app-shell/`](../src/components/core-app-shell/)
|
**Source**: `packages/ui/src/components/core-app-shell/`
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
+6
-2
@@ -1,4 +1,8 @@
|
|||||||
# Form UI Library — Architecture & Usage Guide
|
---
|
||||||
|
outline: [2, 3]
|
||||||
|
---
|
||||||
|
|
||||||
|
# Form UI Library
|
||||||
|
|
||||||
> **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 v7, Zod v3, Mantine v8, `@repo/core-i18n`
|
||||||
@@ -56,7 +60,7 @@ withRHF<MantineComponentProps>(displayName, MantineComponent, options?)
|
|||||||
└── Preserves full Mantine TypeScript generics
|
└── Preserves full Mantine TypeScript generics
|
||||||
```
|
```
|
||||||
|
|
||||||
**Source**: [`withRHF.tsx`](../src/components/Form/withRHF.tsx)
|
**Source**: `packages/ui/src/components/Form/withRHF.tsx`
|
||||||
|
|
||||||
The factory accepts three arguments:
|
The factory accepts three arguments:
|
||||||
|
|
||||||
@@ -22,7 +22,7 @@ The centralized UI component library for the monorepo. Provides consistent desig
|
|||||||
|
|
||||||
## 📋 Form UI Library
|
## 📋 Form UI Library
|
||||||
|
|
||||||
> **Full Documentation**: [docs/FORM-COMPONENTS.md](docs/FORM-COMPONENTS.md)
|
> **Full Documentation**: [FORM-COMPONENTS.md](./FORM-COMPONENTS.md)
|
||||||
|
|
||||||
The Form UI Library wraps **all 22 applicable Mantine form components** with React Hook Form via a single `withRHF()` HOC factory. Key features:
|
The Form UI Library wraps **all 22 applicable Mantine form components** with React Hook Form via a single `withRHF()` HOC factory. Key features:
|
||||||
|
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<!-- Blok Utama: Ungu lebih terang agar kontras di latar gelap -->
|
||||||
|
<rect x="6" y="6" width="16" height="16" rx="4" fill="#8a57f3"/>
|
||||||
|
<!-- Blok Sekunder: Sedikit lebih terang -->
|
||||||
|
<rect x="18" y="18" width="16" height="16" rx="4" fill="#8a57f3" fill-opacity="0.8"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 374 B |
@@ -0,0 +1,6 @@
|
|||||||
|
<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<!-- Blok Utama (Brand Color) -->
|
||||||
|
<rect x="6" y="6" width="16" height="16" rx="4" fill="#652ed9"/>
|
||||||
|
<!-- Blok Sekunder (Memberikan kesan struktur & kedalaman) -->
|
||||||
|
<rect x="18" y="18" width="16" height="16" rx="4" fill="#652ed9" fill-opacity="0.6"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 359 B |
@@ -0,0 +1,75 @@
|
|||||||
|
# Local Development Setup
|
||||||
|
|
||||||
|
## 🚀 Getting Started
|
||||||
|
|
||||||
|
### Prerequisites
|
||||||
|
|
||||||
|
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
|
||||||
|
* **pnpm**: `v8.15.6`
|
||||||
|
(Enforced via the `packageManager` field in `package.json`)
|
||||||
|
|
||||||
|
### Installation
|
||||||
|
|
||||||
|
Install all dependencies from the **root directory**:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pnpm install
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🛠 Usage & Scripts
|
||||||
|
|
||||||
|
This repository uses **Turborepo** to orchestrate tasks efficiently. All commands are executed from the root.
|
||||||
|
|
||||||
|
### Development
|
||||||
|
|
||||||
|
| Command | Description |
|
||||||
|
| -------------------- | ---------------------------------------------------------------------------------- |
|
||||||
|
| `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: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:desktop` | Start the **Web App + Electron** in parallel for desktop development |
|
||||||
|
|
||||||
|
> [!NOTE]
|
||||||
|
> **Port Topology**: `electron-vite` dynamically allocates a background port (usually `5174`) for its internal renderer shell during `pnpm dev:desktop`. We strictly isolate `web` (`5173`) and `landing` (`3000`) onto separate port ranges to prevent race conditions during parallel execution.
|
||||||
|
|
||||||
|
### Building & Quality
|
||||||
|
|
||||||
|
| Command | Description |
|
||||||
|
| --------------------- | ------------------------------------------------------- |
|
||||||
|
| `pnpm build` | Build all apps and packages using Turbo cache |
|
||||||
|
| `pnpm build:web` | Build only the web application |
|
||||||
|
| `pnpm build:landing` | Build only the landing page |
|
||||||
|
| `pnpm build:docs-dev` | Build only the docs-dev application |
|
||||||
|
| `pnpm build:desktop` | Build the web app, then compile the Electron app |
|
||||||
|
| `pnpm test` | Run unit tests (Vitest) across all packages |
|
||||||
|
| `pnpm lint` | Run ESLint across the workspace |
|
||||||
|
| `pnpm format` | Format code using Prettier |
|
||||||
|
|
||||||
|
### 🚀 Desktop Packaging & Distribution
|
||||||
|
|
||||||
|
To package the application into a production-ready installer, use the following commands from the **root directory**:
|
||||||
|
|
||||||
|
| Command | Platform | Output Artifact |
|
||||||
|
| ---------------------- | ----------- | ------------------------------------------ |
|
||||||
|
| `pnpm package:desktop` | Current OS | Detects host OS and builds accordingly |
|
||||||
|
| `pnpm package:mac` | macOS | `.dmg` and `.zip` (supports x64 & arm64) |
|
||||||
|
| `pnpm package:win` | Windows | `.exe` (NSIS Installer) |
|
||||||
|
| `pnpm package:linux` | Linux | `.AppImage` |
|
||||||
|
|
||||||
|
> [!IMPORTANT]
|
||||||
|
> **Build Sequence**: All `package:*` commands execute the following pipeline automatically:
|
||||||
|
>
|
||||||
|
> 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/`.
|
||||||
|
> 3. **`electron-builder`** — 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.
|
||||||
|
|
||||||
|
> [!WARNING]
|
||||||
|
> **macOS Code Signing**: To build a distributable macOS app with Auto-Update support, you **must** have an Apple Developer Certificate and provide `CSC_LINK` and `CSC_KEY_PASSWORD` in your environment. Without code signing, macOS Gatekeeper will block the app and auto-updates will fail. See the Desktop documentation for details.
|
||||||
|
|
||||||
|
> [!NOTE]
|
||||||
|
> **Cross-Compilation**: It is highly recommended to build for Windows on a Windows machine and for macOS on a Mac. Cross-compilation (e.g., building `.dmg` on Linux) may fail due to platform-specific toolchain dependencies. Use a CI matrix strategy (e.g., GitHub Actions with `runs-on: [macos-latest, windows-latest, ubuntu-latest]`) for multi-platform releases.
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
import type { Meta, StoryObj } from '@storybook/react';
|
|
||||||
import { Button } from '@repo/ui';
|
|
||||||
|
|
||||||
const meta: Meta<typeof Button> = {
|
|
||||||
component: Button,
|
|
||||||
argTypes: {
|
|
||||||
type: {
|
|
||||||
control: { type: 'radio' },
|
|
||||||
options: ['button', 'submit', 'reset'],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
export default meta;
|
|
||||||
|
|
||||||
type Story = StoryObj<typeof Button>;
|
|
||||||
|
|
||||||
/*
|
|
||||||
*👇 Render functions are a framework specific feature to allow you control on how the component renders.
|
|
||||||
* See https://storybook.js.org/docs/react/api/csf
|
|
||||||
* to learn how to use render functions.
|
|
||||||
*/
|
|
||||||
export const Primary: Story = {
|
|
||||||
render: (props) => (
|
|
||||||
<Button
|
|
||||||
{...props}
|
|
||||||
onClick={(): void => {
|
|
||||||
// eslint-disable-next-line no-alert -- alert for demo
|
|
||||||
alert('Hello from Turborepo!');
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Hello
|
|
||||||
</Button>
|
|
||||||
),
|
|
||||||
name: 'Button',
|
|
||||||
args: {
|
|
||||||
children: 'Hello',
|
|
||||||
type: 'submit',
|
|
||||||
style: {
|
|
||||||
color: 'blue',
|
|
||||||
border: '1px solid gray',
|
|
||||||
padding: 10,
|
|
||||||
borderRadius: 10,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
export default {
|
||||||
|
vite: {
|
||||||
|
optimizeDeps: {
|
||||||
|
include: ['@repo/ui', 'mermaid', 'dayjs']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
import { defineConfig } from 'vitepress'
|
||||||
|
import { withMermaid } from 'vitepress-plugin-mermaid'
|
||||||
|
|
||||||
|
const baseConfig = withMermaid(
|
||||||
|
defineConfig({
|
||||||
|
title: "Test",
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
console.log("Before:", baseConfig.vite.optimizeDeps.include);
|
||||||
|
baseConfig.vite.optimizeDeps.include = baseConfig.vite.optimizeDeps.include.filter(
|
||||||
|
(dep) => !['@braintree/sanitize-url', 'debug', 'cytoscape-cose-bilkent', 'cytoscape'].includes(dep)
|
||||||
|
);
|
||||||
|
console.log("After:", baseConfig.vite.optimizeDeps.include);
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
import { defineConfig } from 'vite';
|
|
||||||
import react from '@vitejs/plugin-react';
|
|
||||||
|
|
||||||
export default defineConfig({ plugins: [react()] });
|
|
||||||
Generated
+1517
-946
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user