Merge pull request 'docs/dev' (#19) from docs/dev into main

Reviewed-on: eigen/fe-monorepo-template#19
This commit is contained in:
2026-06-24 09:36:34 +00:00
30 changed files with 2319 additions and 1414 deletions
+9 -4
View File
@@ -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": {
+4
View File
@@ -44,3 +44,7 @@ web-dist/
# Legacy Code (if applicable) # Legacy Code (if applicable)
legacy/ legacy/
# VitePress
**/.vitepress/cache/
**/.vitepress/dist/
+13 -306
View File
@@ -10,324 +10,31 @@
![Vitest](https://img.shields.io/badge/Vitest-Testing-green?style=flat\&logo=vitest) ![Vitest](https://img.shields.io/badge/Vitest-Testing-green?style=flat\&logo=vitest)
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
``` ```
--- ---
-29
View File
@@ -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.
-38
View File
@@ -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;
+9 -14
View File
@@ -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"
} }
} }
+95
View File
@@ -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
@@ -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 |
+265
View File
@@ -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>
+169
View File
@@ -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`)
@@ -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/`
--- ---
@@ -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:
+6
View File
@@ -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

+6
View File
@@ -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

+75
View File
@@ -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.
-46
View File
@@ -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,
},
},
};
+7
View File
@@ -0,0 +1,7 @@
export default {
vite: {
optimizeDeps: {
include: ['@repo/ui', 'mermaid', 'dayjs']
}
}
}
+14
View File
@@ -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);
-4
View File
@@ -1,4 +0,0 @@
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
export default defineConfig({ plugins: [react()] });
+1517 -946
View File
File diff suppressed because it is too large Load Diff