12 KiB
Frontend Monorepo Template
A scalable, enterprise-ready Web & Desktop monorepo built with Turborepo, pnpm, Vite, and Electron. This repository is designed for long-term maintainability, featuring:
- 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
The monorepo is organized into Apps (deployable applications) and Packages (shared libraries).
.
├── apps/
│ ├── web/ # Main React Application (Vite + TypeScript)
│ ├── 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)
│ ├── 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
Prerequisites
Ensure your local environment matches the following versions to avoid compatibility issues:
- Node.js:
v20+(tested withv24.11.1) — required for the--import tsxflag used by the desktop prebuild script - pnpm:
v8.15.6(Enforced via thepackageManagerfield inpackage.json)
Installation
Install all dependencies from the root directory:
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-vitedynamically allocates a background port (usually5174) for its internal renderer shell duringpnpm dev:desktop. We strictly isolateweb(5173) andlanding(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:
turbo run build --filter=web— Compiles the React SPA intoapps/web/dist/.prebuildhook — Runsnode --import tsx scripts/copy-web-dist.ts, which copiesapps/web/dist/→apps/desktop/web-dist/.electron-builder— Bundlesweb-dist/into the packaged app via thefilesandextraResourcesblocks inelectron-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_LINKandCSC_KEY_PASSWORDin your environment. Without code signing, macOS Gatekeeper will block the app and auto-updates will fail. See 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
.dmgon Linux) may fail due to platform-specific toolchain dependencies. Use a CI matrix strategy (e.g., GitHub Actions withruns-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 wrapapps/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 | Target app switching, app:// protocol internals, HashRouter fallback |
| AUTO_UPDATER.md | Release workflow, CI/CD variables, provider switching, code signing |
| 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/uiand utilities from@repo/utils - Locked to port 3000 (
strictPort: true) — evacuated from the517xrange to avoidelectron-viteport 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/uiare 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 | 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
7. 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.
8. packages/ui
Shared UI component library (Buttons, Inputs, Cards, Layouts).
- Ensures consistent design across all applications
- Designed to be consumed by both web apps and Storybook
9. packages/configs
Single source of truth for tooling configuration.
- eslint-config: Shared ESLint rules (React, libraries, Storybook)
- typescript-config: Shared
tsconfig.jsonbase 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):
rm -rf node_modules **/*/node_modules .turbo **/*/.turbo dist **/*/dist out **/*/out web-dist **/*/web-dist release **/*/release
📝 License
This project is private and proprietary.