This document describes the development environment setup, build pipeline, testing strategies, and contribution workflows for the Prompt Optimizer monorepo. It covers tooling configuration, script execution order, and best practices for local development and continuous integration.
For deployment configurations and environment variables, see Environment Configuration and API Keys. For platform-specific build artifacts and distribution, see Desktop Distribution.
The project enforces strict Node.js version compatibility through engine constraints defined in package.json6-10:
| Requirement | Specification |
|---|---|
| Node.js | ^18.0.0 || ^20.0.0 || ^22.0.0 |
| Package Manager | pnpm 10.6.1+ (enforced) |
| npm/yarn | Blocked with error messages |
The project uses packageManager field to enforce pnpm usage. Attempting to use npm or yarn will result in Chinese error messages directing developers to use pnpm.
Sources: package.json1-10 package.json44
The monorepo uses pnpm workspaces to manage six packages with internal dependencies:
Packages must be built in dependency order to satisfy workspace protocol links:
Phase 1: Foundation
@prompt-optimizer/core - Business logic, no internal dependenciesPhase 2: UI Layer
@prompt-optimizer/ui - Depends on corePhase 3: Applications
@prompt-optimizer/web - Depends on UI@prompt-optimizer/extension - Depends on UI@prompt-optimizer/desktop - Depends on core (uses web build artifacts)@prompt-optimizer/mcp-server - Depends on coreSources: pnpm-lock.yaml10-456 packages/ui/package.json39 packages/web/package.json16
Sources: package.json11-52 packages/core/package.json17 packages/desktop/package.json11-13
The core package uses tsup to compile TypeScript into multiple module formats:
| Output | Format | Purpose |
|---|---|---|
dist/index.js | ESM | Modern module bundlers, Node.js with type: "module" |
dist/index.cjs | CommonJS | Legacy Node.js compatibility, Electron main process |
dist/index.d.ts | TypeScript definitions | Type checking for consumers |
Build Command:
Development Mode:
The --watch flag enables hot-reload by regenerating outputs when source files change.
Sources: packages/core/package.json17-18 packages/core/package.json1-15
The UI package uses vite to build a reusable component library with CSS:
Outputs:
dist/index.js - ESM entry pointdist/index.cjs - CommonJS entry pointdist/index.d.ts - TypeScript definitions (via vite-plugin-dts)dist/style.css - Component stylesVite Configuration Features:
vite-plugin-dtsBuild Command:
Development Mode (Watch):
Sources: packages/ui/package.json26-27 packages/ui/package.json10-19
The web package uses vite to build a single-page application:
Normal Build:
Electron Build Mode:
The ELECTRON_BUILD environment variable triggers special handling:
./ for relative asset loading in Electronpackages/web/dist as usualpackages/desktop/web-distDevelopment Server:
The --force flag clears vite cache to ensure fresh builds after core/UI changes.
Sources: packages/web/package.json6-9 packages/desktop/package.json12
The extension package uses vite with special manifest processing:
Build Process:
public/manifest.json to distManifest Structure:
The extension uses Manifest V3 with a service worker background script.
Build Command:
Sources: packages/extension/package.json8 packages/extension/public/manifest.json1-34
The desktop build is a two-phase process:
This command:
packages/web/dist to packages/desktop/web-distelectron-builder Configuration from packages/desktop/package.json32-90:
| Platform | Targets | Artifacts |
|---|---|---|
| Windows | NSIS installer, ZIP | PromptOptimizer-{version}-win-{arch}.exePromptOptimizer-{version}-win-{arch}.zip |
| macOS | DMG, ZIP (x64 + arm64) | PromptOptimizer-{version}-mac-{arch}.dmgPromptOptimizer-{version}-mac-{arch}.zip |
| Linux | AppImage, ZIP | PromptOptimizer-{version}-linux-{arch}.AppImagePromptOptimizer-{version}-linux-{arch}.zip |
Auto-Update Configuration:
The desktop app checks GitHub releases for updates using electron-updater.
Sources: packages/desktop/package.json11-13 packages/desktop/package.json32-90
The MCP server uses tsup to create a standalone CLI binary:
Build Command:
Outputs:
dist/index.js / dist/index.cjs - Server implementationdist/start.js / dist/start.cjs - CLI entry point (marked as bin in package.json)dist/index.d.ts - Type definitionsBinary Configuration:
After installation, the server can be invoked as prompt-optimizer-mcp.
Sources: packages/mcp-server/package.json12 packages/mcp-server/package.json8-10
Sources: package.json20-26 package.json11-19
This script executes:
pnpm run kill:dev - Kills any running dev processes (Node.js port conflicts)pnpm run clean - Removes all dist folders and vite cachepnpm install - Ensures dependencies are installedpnpm run dev - Starts parallel development modeWhat dev does:
The UI package rebuilds on file changes, and the web dev server serves the application at http://localhost:5173 (default vite port).
Sources: package.json20-22 package.json41-43
This executes:
pnpm run kill:dev - Kill existing processespnpm run clean - Clean build artifactspnpm install - Install dependenciespnpm run dev:desktop:parallel - Start desktop + web in parallelParallel Execution:
This starts:
http://localhost:5173Electron Development Mode:
In development mode packages/desktop/package.json14 the Electron main process loads from the dev server instead of web-dist files.
Sources: package.json24-26 packages/desktop/package.json14
Kill Development Processes:
This script package.json59 runs a Node.js script that forcefully terminates:
Useful when processes hang or ports are in use.
Clean Build Artifacts:
Sources: package.json41-43 package.json59
pnpm provides -F (filter) flag to target specific packages:
Recursive Commands:
The -r flag executes commands in topological order based on workspace dependencies.
Sources: package.json28 package.json13-14
Sources: package.json27-40 packages/core/tests/utils/vcr.ts packages/ui/tests/utils/error-detection.ts tests/e2e/fixtures.ts
The VCR (Video Cassette Recorder) system enables offline testing by recording real LLM API responses and replaying them in subsequent test runs. This eliminates API costs in CI and ensures deterministic test results.
Architecture:
| Component | Purpose | Location |
|---|---|---|
| vcr.ts | VCR mode control and fixture management | packages/core/tests/utils/vcr.ts |
| llm-mock-service.ts | MSW handlers for LLM providers | packages/core/tests/utils/llm-mock-service.ts |
| stream-simulator.ts | Simulates streaming responses | packages/core/tests/utils/stream-simulator.ts |
| fixtures/ | Stored API responses | packages/core/tests/fixtures/ |
| setup.js | Global MSW integration | packages/core/tests/setup.js |
VCR Modes:
Environment Variables:
| Variable | Values | Purpose |
|---|---|---|
VCR_MODE | auto, record, replay, off | Controls VCR behavior |
ENABLE_REAL_LLM | true, false | Allows real API access (for record/off modes) |
E2E_VCR_MODE | record, replay | E2E-specific VCR mode |
Fixture Structure:
Fixtures are stored as JSON files organized by provider and scenario:
packages/core/tests/fixtures/
└── llm/
├── deepseek/
│ ├── optimize-simple-prompt.json
│ └── stream-response.json
├── openai/
│ ├── chat-completion.json
│ └── error-handling.json
└── gemini/
└── multi-turn-conversation.json
Each fixture contains:
Usage in Tests:
Sources: packages/core/tests/utils/vcr.ts packages/core/tests/utils/llm-mock-service.ts packages/core/tests/setup.js docs/testing/vcr-usage-guide.md
The testing system automatically detects and fails tests on UI errors that would otherwise only be visible in browser console:
Vitest Environment (UI Package):
packages/ui/tests/utils/error-detection.ts implements global error handlers:
Integrated in packages/ui/tests/setup.ts to apply globally to all UI tests.
Playwright Environment (E2E Tests):
tests/e2e/fixtures.ts exports custom test and expect with error listeners:
All E2E tests import from ./fixtures instead of @playwright/test.
Ignored Errors:
Both systems support ignore patterns for legitimate warnings:
Sources: packages/ui/tests/utils/error-detection.ts packages/ui/tests/setup.ts tests/e2e/fixtures.ts docs/workspace/testing-redesign/architecture.md
Test gates provide fast feedback loops while ensuring quality:
Fast Gate (Pre-commit):
Executes in < 1 minute package.json36:
test:gate:core)test:gate:ui)Full Gate (CI):
Adds E2E regression suite package.json37:
test:gate:e2e)E2E Gate:
Runs only critical E2E smoke tests package.json35:
tests/e2e/regression.spec.ts - Basic functionality regressiontests/e2e/workflows/p0-route-smoke.spec.ts - Core route accessibilityPre-commit Hook:
.husky/pre-commit automatically runs fast gate:
Sources: package.json33-37 .husky/pre-commit docs/workspace/testing-redesign/progress.md
| Command | Tests Run | Time | Environment | Use Case |
|---|---|---|---|---|
pnpm test | All unit + integration (auto VCR) | ~2-3 min | Local dev | Quick validation |
pnpm test:gate | Fast gate (240 tests) | < 1 min | Pre-commit | Blocking quality gate |
pnpm test:gate:full | Fast gate + E2E (257 tests) | < 10 min | CI | Merge requirement |
pnpm test:replay | All tests (strict VCR) | ~3-4 min | CI | Offline CI runs |
pnpm test:record | All tests (real API) | ~10-15 min | Manual | Update fixtures |
pnpm test:e2e | All E2E tests | ~2-3 min | Local/CI | Full browser coverage |
pnpm test:e2e:smart | Affected E2E subset | ~30-60 sec | CI optimization | Changed files only |
Smart E2E Testing:
scripts/smart-e2e.js analyzes git diff to run only affected E2E tests:
git diffSources: package.json27-40 scripts/smart-e2e.js docs/testing/README.md
Core Package Tests:
Located in packages/core/tests/:
tests/unit/**/*.spec.ts (71 files)tests/integration/**/*.spec.ts (19 files)Run core tests:
UI Package Tests:
Located in packages/ui/tests/:
tests/unit/**/*.spec.ts (18 files)tests/integration/**/*.spec.ts (2 files)tests/e2e/**/*.spec.ts (1 file)Run UI tests:
Key Testing Utilities:
| Utility | Purpose | Location |
|---|---|---|
withVCR() | VCR wrapper for LLM tests | packages/core/tests/utils/vcr.ts |
createTestPinia() | Pinia store testing helper | packages/ui/tests/utils/pinia-test-helpers.ts |
withMockPiniaServices() | Auto-cleanup test wrapper | packages/ui/tests/utils/pinia-test-helpers.ts |
real-llm helpers | Real LLM API integration | packages/core/tests/helpers/ |
Sources: packages/core/package.json19-24 packages/ui/package.json28 packages/core/tests/ packages/ui/tests/
Configuration:
playwright.config.ts defines:
Test Organization:
Located in tests/e2e/:
regression.spec.ts - Basic functionality smoke testsworkflows/ - Multi-step user workflowsfixtures.ts - Custom Playwright fixtures with error gatesRun E2E tests:
VCR Mode in E2E:
Sources: playwright.config.ts tests/e2e/ package.json29-32
The project uses ESLint with TypeScript support:
Configuration: packages/ui/.eslintrc.json
Linting rules are defined in .eslintrc.json and enforce:
@typescript-eslint/eslint-plugineslint-plugin-vueESLint Scope:
Sources: package.json54-55 packages/ui/package.json30-31
TypeScript type checking is performed separately from builds:
Type Check Command:
The --noEmit flag checks types without generating output files (build handles output).
tsconfig Configuration:
tsconfig.json@vue/tsconfig for Vue projectsSources: packages/ui/package.json29 packages/mcp-server/package.json17
From .cursorrules19-36 the project maintains two documentation files:
experience.md - Long-term knowledge:
scratchpad.md - Working memory:
Documentation Update Requirements:
experience.md with root cause analysisscratchpad.mdSources: .cursorrules19-64
From .cursorrules110-115 reviewers should verify:
Sources: .cursorrules110-115
Version Synchronization:
scripts/sync-versions.js ensures all packages use the same version:
package.json (currently 2.5.4)version field in all workspace package.json filesLocal Release Workflow:
Automated Git Hook:
package.json46 defines a lifecycle script that runs after pnpm version:
This ensures version changes are automatically staged.
CI/CD Release Trigger:
Pushing a git tag triggers .github/workflows/release.yml:
v*.*.* (e.g., v2.5.4)v*.*.*-beta.1, v*.*.*-rc.2package.json in each platform build jobVersion Constraints:
| Constraint | Value | Purpose |
|---|---|---|
| Package Manager | [email protected] | Enforced consistency |
| Lockfile Version | 9.0 | pnpm lockfile format |
| Node.js Engines | ^18.0.0 || ^20.0.0 || ^22.0.0 | Supported Node versions |
| Dependency Override | [email protected] | Fixes electron-builder issue |
Desktop Application Versioning:
The release workflow .github/workflows/release.yml44-115 modifies packages/desktop/package.json during build:
This ensures installer metadata matches the release tag.
Extension Manifest Versioning:
packages/extension/public/manifest.json5 must be manually updated before release:
Chrome Web Store requires exact version match with manifest.
Sources: package.json45-49 package.json3 package.json99-106 .github/workflows/release.yml44-115 packages/extension/public/manifest.json5
Sources: package.json41-43
View Logs:
This opens the logs directory at %APPDATA%\PromptOptimizer\logs.
Clear Logs:
Log Locations by Platform:
%APPDATA%\PromptOptimizer\logs~/Library/Application Support/PromptOptimizer/logs~/.config/PromptOptimizer/logsSources: packages/desktop/package.json15-16
Start MCP Server (HTTP Mode):
This runs packages/mcp-server/package.json13:
The -r ./preload-env.js flag loads environment variables from .env before execution.
Test MCP Server:
Production Start:
Uses the CommonJS build (dist/start.cjs) for better compatibility.
Sources: packages/mcp-server/package.json12-15
All Platforms:
This executes in order package.json12:
build:core - Core package (tsup)build:ui - UI package (vite)build:parallel - Web + Extension in parallelDesktop Only:
Builds core, UI, web, then packages desktop application package.json19
Sources: package.json12-19
Sources: .github/workflows/test.yml .github/workflows/release.yml .github/workflows/docker.yml
Trigger Conditions:
main or master branchesmain or masterworkflow_call)Execution Steps:
.github/workflows/test.yml17-49 defines a single test job on ubuntu-latest:
actions/checkout@v6pnpm/action-setup@v4pnpm installpnpm test:gate (Core + UI tests, 240 tests)pnpm exec playwright install --with-deps chromiumpnpm test:gate:e2e (17 critical E2E tests)
E2E_VCR_MODE=replay (strict offline mode)Total execution time: Typically 5-8 minutes
Key configurations:
actions/setup-node@v6**.md and docs/** (skip on doc-only changes)Sources: .github/workflows/test.yml1-49
Trigger Conditions:
v*.*.* (e.g., v2.5.4)v*.*.*-* (e.g., v2.5.4-beta.1)Multi-Stage Process:
.github/workflows/release.yml19-20 calls test.yml workflow first. Release only proceeds if all tests pass.
Three parallel jobs build desktop applications:
Windows Build .github/workflows/release.yml23-154:
windows-latestpnpm build:desktop.exe installer + .zip portable + .yml auto-update manifestactions/upload-artifact@v6 (30-day retention)macOS Build .github/workflows/release.yml156-280:
macos-latestpnpm build:desktop.dmg installers (x64 + arm64).zip portable archives (x64 + arm64).yml auto-update manifestsLinux Build .github/workflows/release.yml282-406:
ubuntu-latestpnpm build:desktop.AppImage + .zip + .yml auto-update manifestArtifact Verification:
Each build job includes verification .github/workflows/release.yml124-144:
.github/workflows/release.yml408-670 unifies artifacts and publishes:
builder-debug.yml filessoftprops/action-gh-release@v2Version Detection Logic .github/workflows/release.yml438-458:
| Pattern | Type | Prerelease Flag | Example |
|---|---|---|---|
v*.*.* | Stable release | false | v2.5.4 |
v*.*.*-alpha | Alpha | true | v2.5.4-alpha.1 |
v*.*.*-beta | Beta | true | v2.5.4-beta.1 |
v*.*.*-rc | Release candidate | true | v2.5.4-rc.1 |
v*.*.*-hotfix | Hotfix | false | v2.5.4-hotfix.1 |
Auto-Update Integration:
The .yml manifest files enable Electron auto-updater:
Sources: .github/workflows/release.yml1-670 packages/desktop/package.json32-90
Trigger Conditions:
test.yml workflow on main/masterworkflow_dispatchConditional Execution:
Only runs if .github/workflows/docker.yml20:
test.yml succeeded AND push event on main/masterMulti-Architecture Build:
.github/workflows/docker.yml26-71 performs:
Version extraction from package.json .github/workflows/docker.yml32-37:
Registry login (dual-push):
docker.io/linshen/prompt-optimizerregistry.cn-guangzhou.aliyuncs.com/prompt-optimizer/prompt-optimizerQEMU setup for cross-compilation .github/workflows/docker.yml52-53
Docker Buildx with platforms .github/workflows/docker.yml62:
Multi-tag push .github/workflows/docker.yml64-68:
linshen/prompt-optimizer:2.5.4linshen/prompt-optimizer:latestregistry.cn-guangzhou.aliyuncs.com/.../prompt-optimizer:2.5.4registry.cn-guangzhou.aliyuncs.com/.../prompt-optimizer:latestBuild cache optimization .github/workflows/docker.yml69-70:
Docker Image Contents:
From the Dockerfile (implied structure):
packages/web/dist)packages/mcp-server/dist)Sources: .github/workflows/docker.yml1-71
Parallel Execution:
Caching:
setup-node action (reduces install time by 80%)Smart Test Execution:
Path Filtering:
test.yml ignores **.md and docs/** changesConditional Workflows:
Sources: .github/workflows/test.yml5-8 .github/workflows/docker.yml20 .github/workflows/release.yml409
From .cursorrules93-109 the standard workflow is:
1. Feature Development:
2. Bug Fixes:
3. Pre-Commit:
Sources: .cursorrules93-109
From .cursorrules10-18 every code change must:
npm run test (maps to pnpm run test)Sources: .cursorrules10-18
Before submitting a PR, update:
From .cursorrules119-125 required reading before contribution:
fileNames.md - Project file mapdocs/prd.md - Product requirementsdocs/app-flow.md - Application flow diagramsdocs/tech-stack.md - Technology stack overviewdocs/file-structure.md - Directory structuredocs/frontend-guidelines.md - Frontend development standardsSources: .cursorrules119-125 .cursorrules19-36
This comprehensive build and workflow system ensures consistent development across all platforms while maintaining high code quality through automated testing and standardized processes. The monorepo structure enables code sharing while the flexible build pipeline supports diverse deployment targets from web apps to desktop applications to MCP servers.
Refresh this wiki