The User Interface Layer (packages/ui) implements the complete presentation tier for Prompt Optimizer. This layer provides Vue 3 components, composables, and styling that render the application across all deployment targets (web, desktop, extension, MCP). It consumes services from the Core Services Layer (see Core Services Layer) and implements mode-specific workflows, internationalization, session management, and responsive layouts.
This document covers:
For platform-specific adaptations, see Platform Implementations. For core business logic, see Core Services Layer.
The @prompt-optimizer/ui package exports components, composables, and utilities through packages/ui/src/index.ts1-254 The package follows a modular architecture with components organized by functional domain:
Directory Structure:
packages/ui/src/
├── components/
│ ├── app-layout/ # Application shell
│ │ ├── PromptOptimizerApp.vue
│ │ ├── AppHeaderActions.vue
│ │ └── AppCoreNav.vue
│ ├── basic-mode/ # Basic optimization workspaces
│ │ ├── BasicSystemWorkspace.vue
│ │ └── BasicUserWorkspace.vue
│ ├── context-mode/ # Pro mode (advanced) workspaces
│ │ ├── ContextSystemWorkspace.vue
│ │ ├── ContextUserWorkspace.vue
│ │ ├── ConversationManager.vue
│ │ └── ContextEditor.vue
│ ├── image-mode/ # Image generation workspaces
│ │ ├── ImageText2ImageWorkspace.vue
│ │ ├── ImageImage2ImageWorkspace.vue
│ │ └── ImageModeSelector.vue
│ ├── variable/ # Variable management
│ │ ├── VariableManagerModal.vue
│ │ ├── VariableEditor.vue
│ │ └── variable-extraction/
│ ├── evaluation/ # Evaluation system
│ │ ├── EvaluationPanel.vue
│ │ ├── EvaluateButton.vue
│ │ └── EvaluationScoreBadge.vue
│ ├── ModelManager.vue # Model configuration UI
│ ├── TemplateManager.vue # Template library UI
│ ├── HistoryDrawer.vue # History browser
│ ├── PromptPanel.vue # Output display panel
│ ├── InputPanel.vue # Input editor panel
│ ├── TestAreaPanel.vue # Testing interface
│ └── ...
├── composables/ # Reusable logic
│ ├── prompt/
│ ├── model/
│ ├── mode/
│ ├── variable/
│ ├── session/
│ └── ui/
├── stores/ # Pinia state stores
│ ├── session/
│ └── settings/
├── router/ # Vue Router configuration
├── i18n/ # Internationalization
│ └── locales/
└── styles/ # Global CSS
Component Categories:
| Category | Purpose | Key Components | File Paths |
|---|---|---|---|
| app-layout | Application shell, navigation, header | PromptOptimizerApp, AppCoreNav, AppHeaderActions | components/app-layout/*.vue |
| basic-mode | Basic system/user prompt optimization | BasicSystemWorkspace, BasicUserWorkspace | components/basic-mode/*.vue |
| context-mode | Pro mode with variables and conversations | ContextSystemWorkspace, ContextUserWorkspace, ConversationManager | components/context-mode/*.vue |
| image-mode | Image generation workspaces | ImageText2ImageWorkspace, ImageImage2ImageWorkspace | components/image-mode/*.vue |
| Management UIs | Model/template/history/data/favorites | ModelManager, TemplateManager, HistoryDrawer, DataManager, FavoriteManager | components/*.vue |
| Input/Output | Prompt input and result display | InputPanel, PromptPanel, OutputDisplay | components/*.vue |
| Testing | Multi-column test variants | TestAreaPanel, TestControlBar, TestResultSection | components/Test*.vue |
| Variable | Variable management and extraction | VariableManagerModal, VariableEditor | components/variable/*.vue |
| Evaluation | Prompt evaluation and scoring | EvaluationPanel, EvaluateButton, EvaluationScoreBadge | components/evaluation/*.vue |
Export Strategy:
packages/ui/src/index.ts49-254 exports all public components with a UI suffix (e.g., ModelManagerUI, ToastUI) to avoid naming conflicts. Platform applications import these components directly.
Sources: packages/ui/src/index.ts1-254
PromptOptimizerApp.vue serves as the top-level orchestration component consumed by all platform entry points:
Platform Entry Points - Code Mapping:
Initialization Sequence:
packages/ui/src/components/app-layout/PromptOptimizerApp.vue383-407
useAppInitializer() creates ModelManager, TemplateManager, HistoryManager, PromptService, etc.useFunctionMode(), useBasicSubMode(), useProSubMode(), useImageSubMode() initialize mode preferencescomputed properties that parse route paths as single source of truthinitializeI18nWithStorage() at mount, setI18nServices() when services readysetPiniaServices() injects core services into session storesuseNaiveTheme() provides reactive theme configurationRouterView Dynamic Workspace Loading:
packages/ui/src/components/app-layout/PromptOptimizerApp.vue55-68
Routes like /basic/system or /pro/variable dynamically load corresponding workspace components (BasicSystemWorkspace, ContextUserWorkspace, etc.).
Sources: packages/ui/src/components/app-layout/PromptOptimizerApp.vue1-850 packages/web/src/App.vue1-26 packages/extension/src/App.vue1-26
The UI layer supports three locales with complete message coverage defined in packages/ui/src/i18n/locales/ Each locale file exports a single default object with nested message keys.
Locale File Structure (Code Entities):
Message Key Examples (Actual Keys from Code):
| Key Path | en-US | zh-CN | zh-TW |
|---|---|---|---|
common.optimize | "Optimize" | "优化" | "優化" |
promptOptimizer.originalPrompt | "Original Prompt" | "原始提示词" | "原始提示詞" |
test.compareMode | "Compare Mode" | "对比模式" | "對比模式" |
variables.predefined | "Predefined Variables" | "预定义变量" | "預定義變數" |
contextMode.optimizationMode.message | "Multi-Message" | "多消息" | "多訊息" |
contextMode.optimizationMode.variable | "Variable" | "变量" | "變數" |
Language Persistence:
packages/ui/src/i18n/locales/en-US.ts19-105 packages/ui/src/i18n/locales/zh-CN.ts19-104 packages/ui/src/i18n/locales/zh-TW.ts19-104
LanguageSwitchDropdown componenti18n.global.locale.value updatedPreferenceService.set(UI_SETTINGS_KEYS.LANGUAGE, locale) persists choiceuseI18n() reactively update via Vue's reactivity systemFallback Chain:
fallbackLocale optionSources: packages/ui/src/i18n/locales/en-US.ts1-1068 packages/ui/src/i18n/locales/zh-CN.ts1-1068 packages/ui/src/i18n/locales/zh-TW.ts1-1068
Each functional mode has dedicated workspace components that implement the complete optimization workflow:
All workspaces use a two-column split layout with a draggable divider. The layout uses CSS Grid with dynamic column sizing.
Code Structure (ContextUserWorkspace.vue):
Dragging Implementation:
The divider uses pointerdown/pointermove/pointerup events to track drag state. The handler calculates new percentage based on mouse X position and container width, clamping between 25% and 75%.
Persistence:
Split position is saved to PreferenceService with mode-specific keys:
UI_SETTINGS_KEYS.BASIC_SYSTEM_SPLIT_LEFT_PCTUI_SETTINGS_KEYS.BASIC_USER_SPLIT_LEFT_PCTUI_SETTINGS_KEYS.PRO_VARIABLE_SPLIT_LEFT_PCTUI_SETTINGS_KEYS.PRO_MULTI_SPLIT_LEFT_PCTResponsive Behavior:
On screens < 768px, the split switches to stacked vertical layout. The divider becomes horizontal.
Sources: packages/ui/src/components/context-mode/ContextUserWorkspace.vue1-139
Key Props:
packages/ui/src/components/context-mode/ContextUserWorkspace.vue69-94
| Prop | Type | Purpose |
|---|---|---|
prompt | string | Original user prompt |
optimizedPrompt | string | Latest optimized version |
versions | PromptVersion[] | V0, V1, V2... history |
temporaryVariables | Record<string, string> | Session-scoped variables |
testVariants | TestVariant[] | A/B/C/D column configs |
Collapsible Input Panel:
packages/ui/src/components/context-mode/ContextUserWorkspace.vue28-64
The input panel can collapse to a title bar to maximize screen space for results. When collapsed, it shows a prompt summary.
Sources: packages/ui/src/components/context-mode/ContextUserWorkspace.vue1-139
Conversation Manager Integration:
packages/ui/src/components/context-mode/ContextSystemWorkspace.vue15-49
The ConversationManager component provides a full-featured message editor:
Message Optimization Flow:
@message-selectContextSystemWorkspace displays selected message's V0/V1 in PromptPanelUIConversationManagerSources: packages/ui/src/components/context-mode/ContextSystemWorkspace.vue1-100
Variable Extraction Integration:
packages/ui/src/components/context-mode/ContextUserWorkspace.vue88-93
When user clicks "Extract Variables", the UI calls the AI-powered variable extraction service to identify potential variables in the prompt.
Sources: packages/ui/src/components/InputPanel.vue1-200 (referenced but not provided in full)
PromptPanel.vue displays optimized prompt output with version navigation and action buttons. The component integrates OutputDisplay for content rendering and manages version switching state.
Component Structure (PromptPanel.vue):
Version Tag Rendering (Lines 24-60):
Action Button Conditions (Lines 67-209):
| Button | v-if Condition | Emits | Lines |
|---|---|---|---|
| Preview | showPreview && optimizedPrompt | @open-preview | 67-98 |
| Apply to Conversation | showApplyButton && versions.length > 0 | @apply-to-conversation | 100-126 |
| Evaluation Badge | showEvaluation && (optimizedPrompt || evaluationType === 'prompt-only') | @show-detail, @evaluate, @apply-improvement, @apply-patch | 128-167 |
| Save Changes | showSaveChanges | @save-local-edit | 169-177 |
| Iterate | optimizedPrompt | Opens modal | 179-209 |
Evaluation Integration (Lines 382-437):
The component uses useEvaluationContextOptional() to access evaluation state. If Pro mode provides an evaluation context, score badges are displayed. The evaluation type is dynamically determined: prompt-iterate if currentIterationNote exists, otherwise prompt-only.
Sources: packages/ui/src/components/PromptPanel.vue1-600
Mode Switching:
packages/ui/src/components/OutputDisplayCore.vue1-100 (referenced structure)
Users toggle between modes via icon buttons in the header. Diff mode is only available when both original and optimized prompts exist.
Sources: packages/ui/src/components/OutputDisplay.vue1-50 (partial reference)
Compare Mode Toggle:
packages/ui/src/components/TestAreaPanel.vue19-44
When compare mode is enabled, TestResultSection renders two columns (original vs optimized). Otherwise, it shows a single result column.
Sources: packages/ui/src/components/TestAreaPanel.vue1-160
Responsive Behavior:
packages/ui/src/components/TestControlBar.vue147-161
Sources: packages/ui/src/components/TestControlBar.vue1-162
In Pro mode workspaces, the testing system supports 2/3/4 parallel test variants (A/B/C/D):
Variant State Structure:
packages/ui/src/components/context-mode/ContextUserWorkspace.vue220-235
Each variant tracks:
version: Selected prompt version (V0, V1, V2...)modelKey: Selected test modelresult: Test output textrunning: Loading statestale: Configuration changed since last runStaleness Detection:
A variant becomes stale when:
Stale variants display a warning badge and require re-running the test.
Sources: packages/ui/src/components/context-mode/ContextUserWorkspace.vue200-280
Variable List Columns:
| Column | Content | Actions |
|---|---|---|
| Variable Name | {{variableName}} syntax | Click to edit |
| Value | Truncated preview | Click to view full |
| Source | Predefined / Global / Context | Read-only |
| Description | User-provided description | Editable |
| Actions | Edit / Delete buttons | Conditional visibility |
Sources: packages/ui/src/components/variable/VariableManagerModal.vue1-100 (referenced structure)
Variable Priority System:
packages/ui/src/composables/variable/useAggregatedVariables.ts1-50 (referenced logic)
When rendering prompts, variables are resolved with this priority:
Smart Variable Value Generation:
packages/ui/src/components/context-mode/ContextUserTestPanel.vue104-107
The smart generation feature uses an LLM to analyze the optimized prompt and suggest appropriate values for detected variables.
Sources: packages/ui/src/components/variable/TemporaryVariablesPanel.vue1-100 (referenced structure), packages/ui/src/components/context-mode/ContextUserTestPanel.vue1-107
Sources: packages/ui/src/composables/variable/useVariableExtraction.ts1-50 (referenced logic)
Provider Configuration:
packages/ui/src/components/ModelManager.vue1-100 (referenced structure)
Each model requires:
modelKey: Unique identifier (e.g., "my-openai-gpt4")provider: Adapter type (openai, gemini, anthropic, deepseek, etc.)apiUrl: Base URL (e.g., "https://api.openai.com/v1")apiKey: Authentication token (optional, can use env vars)defaultModel: Model name (e.g., "gpt-4-turbo")enabled: Boolean flag for visibility in selectorsAdvanced Parameters:
Users can configure provider-specific parameters like temperature, top_p, max_tokens, stop_sequences, etc. The UI validates parameter types and ranges.
Sources: packages/ui/src/i18n/locales/en-US.ts744-888
Template Type Mapping:
| UI Category | TemplateType | Usage |
|---|---|---|
| System Optimize | optimize | Basic system prompt optimization |
| User Optimize | userOptimize | Basic user prompt optimization |
| System Iterate | iterate | Basic refinement |
| Context Optimize | contextUserOptimize | Pro variable mode optimization |
| Context Iterate | contextIterate | Pro variable mode refinement |
| Conversation Message | conversationMessageOptimize | Pro multi mode message optimization |
| Image T2I | text2imageOptimize | Text-to-image generation |
| Image I2I | image2imageOptimize | Image-to-image transformation |
Advanced Template Format:
packages/ui/src/i18n/locales/en-US.ts926-933
Advanced templates support multi-message structures:
Sources: packages/ui/src/i18n/locales/en-US.ts893-1010
The UI layer extensively uses Vue composables for code reuse across components:
packages/ui/src/composables/prompt/usePromptOptimizer.ts1-50 (referenced structure)
Used by workspace components to handle optimize/iterate button clicks.
useProSubMode manages Pro mode sub-mode state (multi or variable) with singleton pattern and preference persistence.
Code Structure (useProSubMode.ts):
Initialization Flow (Lines 48-80):
getPreference<ProSubMode>(UI_SETTINGS_KEYS.PRO_SUB_MODE, DEFAULT_PRO_SUB_MODE)'system' → 'multi''user' → 'variable''variable'singleton!.mode.value = normalizedsetPreference(UI_SETTINGS_KEYS.PRO_SUB_MODE, normalized)Setter Methods:
Singleton Pattern:
Only one singleton object exists per app lifecycle. All calls to useProSubMode() return references to the same reactive mode ref, ensuring state consistency across components.
Sources: packages/ui/src/composables/mode/useProSubMode.ts1-99
packages/ui/src/composables/variable/useAggregatedVariables.ts1-100 (referenced structure)
This composable merges three variable sources into a single map, used by template processors and preview panels.
packages/ui/src/composables/variable/useTemporaryVariables.ts1-100 (referenced structure)
This pattern ensures temporary variables are stored in the correct Pinia session store.
Each operational mode has a dedicated Pinia store for session state persistence:
All session stores share a common structure:
packages/ui/src/stores/session/useBasicSystemSession.ts1-100 (referenced structure)
Pro Multi Mode:
packages/ui/src/stores/session/useProMultiMessageSession.ts1-100 (referenced structure)
Pro Variable Mode:
packages/ui/src/stores/session/useProVariableSession.ts1-100 (referenced structure)
Image Modes:
packages/ui/src/stores/session/useImageText2ImageSession.ts1-100 (referenced structure)
packages/ui/src/composables/session/useSessionRestoreCoordinator.ts1-100 (referenced structure)
Called during application initialization to restore user's previous session state.
Sources: packages/ui/src/stores/session/useSessionManager.ts1-100 (referenced structure)
Props:
packages/ui/src/components/evaluation/EvaluationScoreBadge.vue1-100 (referenced structure)
| Prop | Type | Description |
|---|---|---|
score | number | null | Evaluation score 0-100 |
level | ScoreLevel | null | excellent, good, fair, poor |
loading | boolean | Show loading spinner |
result | EvaluationResponse | null | Full evaluation data |
type | EvaluationType | prompt-only, A-B, compare |
size | string | small, medium, large |
Events:
| Event | Payload | Purpose |
|---|---|---|
show-detail | void | Open evaluation detail dialog |
evaluate | void | Trigger (re-)evaluation |
apply-improvement | { improvement: string, type: EvaluationType } | Apply suggested improvement |
apply-patch | PatchOperation[] | Apply structured diff patch |
Sources: packages/ui/src/components/evaluation/types.ts1-50 (referenced types)
All platforms consume the same router instance exported by @prompt-optimizer/ui. The router uses hash history to support file:// protocols (Electron, extensions).
Router Export and Integration:
Route Configuration (router/index.ts):
Each route uses dynamic import for code splitting:
This ensures workspace components are only loaded when the user navigates to that route, reducing initial bundle size.
Route Parsing in PromptOptimizerApp (Lines 416-468):
PromptOptimizerApp establishes route-driven state via computed properties:
These computed properties serve as the single source of truth for mode state, replacing legacy reactive refs.
Sources: packages/ui/src/router/index.ts1-100 (referenced), packages/ui/src/index.ts116-117 packages/ui/src/components/app-layout/PromptOptimizerApp.vue416-474
The User Interface Layer provides a comprehensive Vue 3 component architecture that:
@prompt-optimizer/ui packageFor core service integration details, see Core Services Layer. For platform-specific implementations (Electron IPC, browser storage), see Platform Implementations.
Refresh this wiki