This document describes the top-level application shell that wraps all UI functionality, the routing system that maps URLs to workspace components, and the internationalization (i18n) infrastructure that supports multiple languages (en-US, zh-CN, zh-TW). It also covers theme management for visual customization.
For information about individual workspace components (BasicSystemWorkspace, ContextUserWorkspace, etc.), see 3.2. For details on core service initialization and dependency injection, see 2.
The PromptOptimizerApp.vue component (packages/ui/src/components/app-layout/PromptOptimizerApp.vue1-710) serves as the unified application shell for all deployment targets (web, desktop, extension). Platform-specific entry points are thin wrappers that render this single component.
Diagram: Application Shell Component Hierarchy
Sources: packages/ui/src/components/app-layout/PromptOptimizerApp.vue1-710
The PromptOptimizerApp component manages:
The component uses a three-stage loading sequence:
isInitializing = true - Displays spinner while useAppInitializer() runs (line 19)services = null - Shows error message if bootstrap fails (line 23)isReady = true - Full UI renders with all composables initialized (line 30)Sources: packages/ui/src/components/app-layout/PromptOptimizerApp.vue19-30 packages/ui/src/components/app-layout/PromptOptimizerApp.vue383 packages/ui/src/components/app-layout/PromptOptimizerApp.vue416-533
The MainLayoutUI component provides the consistent layout structure across all pages:
Sources: packages/ui/src/components/MainLayout.vue1-64
MainLayoutUI uses Vue slots to allow parent components to inject content:
| Slot Name | Purpose | Filled By |
|---|---|---|
title | Application title | {{ t('promptOptimizer.title') }} |
core-nav | Mode selector (Basic/Context/Image) | AppCoreNav component |
actions | Header actions (templates, history, settings, etc.) | AppHeaderActions component |
main | Primary content area | RouterView (workspace components) |
modals | Global modals/drawers | ModelManager, TemplateManager, etc. |
Sources: packages/ui/src/components/MainLayout.vue11-60 packages/ui/src/components/app-layout/PromptOptimizerApp.vue31-69
The layout adapts to viewport width:
window.innerWidthSources: packages/ui/src/components/MainLayout.vue92-118
The router defines URL-to-workspace mappings using Vue Router. The PromptOptimizerApp implements route-driven architecture where the URL is the single source of truth for application mode.
Diagram: Route Parsing and Mode Computation
Key Implementation Details:
parseRouteInfo() (lines 416-468) - Pure function that extracts mode from URL path:
/basic, /pro, /image)['system', 'user'] for basic)Computed Mode Refs (lines 471-474) - Reactive computed properties:
routeFunctionMode: computed<FunctionMode>(() => parseRouteInfo().functionMode)routeBasicSubMode: computed<BasicSubMode>(() => parseRouteInfo().basicSubMode)routeProSubMode: computed<ProSubMode>(() => parseRouteInfo().proSubMode)routeImageSubMode: computed<ImageSubMode>(() => parseRouteInfo().imageSubMode)Session Manager Integration (lines 528-533) - Injects route readers:
Sources: packages/ui/src/components/app-layout/PromptOptimizerApp.vue231 packages/ui/src/components/app-layout/PromptOptimizerApp.vue416-533
Diagram: URL Path Mapping
Route Configuration:
Routes use lazy loading via dynamic imports. The router instance is imported from packages/ui/src/router/index.ts (line 231) and used directly:
Default Route Handling: The root path / is handled by RootBootstrapRoute component, which waits for globalSettings to initialize before redirecting to the last-used workspace.
Sources: packages/ui/src/components/app-layout/PromptOptimizerApp.vue62-68 packages/ui/src/components/app-layout/PromptOptimizerApp.vue231
| Route Path | Function Mode | Sub-Mode | Workspace File | Optimization Type |
|---|---|---|---|---|
/basic/system | basic | system | BasicSystemWorkspace.vue | System prompt optimization |
/basic/user | basic | user | BasicUserWorkspace.vue | User prompt optimization |
/pro/multi | pro | multi | ContextSystemWorkspace.vue | Multi-message optimization |
/pro/variable | pro | variable | ContextUserWorkspace.vue | Variable-based optimization |
/image/text2image | image | text2image | ImageText2ImageWorkspace.vue | Text-to-image generation |
/image/image2image | image | image2image | ImageImage2ImageWorkspace.vue | Image-to-image generation |
Sub-Mode Validation: The parseRouteInfo() function validates sub-modes against whitelists:
['system', 'user'] (line 434)['multi', 'variable'] (line 435)['text2image', 'image2image'] (line 436)Invalid sub-modes trigger fallback to default: system for basic, variable for pro, text2image for image (lines 446-450).
Sources: packages/ui/src/components/app-layout/PromptOptimizerApp.vue429-455
The application supports three locales: en-US (English), zh-CN (Simplified Chinese), and zh-TW (Traditional Chinese). Internationalization uses vue-i18n with storage-backed locale persistence.
Diagram: i18n Initialization and Message Flow
Initialization Sequence:
Service Watcher (lines 537-544) - Triggered when services become available:
Storage Integration - setI18nServices() injects PreferenceService for locale persistence
Locale Restoration - initializeI18nWithStorage() reads saved locale from storage (defaults to 'en-US' if none)
Sources: packages/ui/src/components/app-layout/PromptOptimizerApp.vue321-322 packages/ui/src/components/app-layout/PromptOptimizerApp.vue537-544 packages/ui/src/i18n/locales/en-US.ts1-1707 packages/ui/src/i18n/locales/zh-CN.ts1-1737 packages/ui/src/i18n/locales/zh-TW.ts1-1642
Each locale file exports a default object with nested message keys:
Message Key Hierarchy:
Top-level namespaces (31 total): common, nav, contextMode, favorites, promptOptimizer, variables, conversation, tools, settings, modelManager, functionModel, templateManager, history, theme, test, variableDetection, template, prompt, output, optimization, model, toast, log, dataManager, params, contextEditor, updater, imageMode, evaluation, imageParams, dev
Deep nesting: Up to 5 levels (e.g., favorites.manager.tagManager.mergeDialog.warning - en-US.ts311)
Interpolation syntax: Uses {varName} for variable substitution (e.g., "version": "V{version}" - en-US.ts56)
Fallback Chain: Traditional Chinese (zh-TW) falls back to Simplified Chinese (zh-CN) for missing keys, which then falls back to English (en-US).
Sources: packages/ui/src/i18n/locales/en-US.ts18-1707 packages/ui/src/i18n/locales/zh-CN.ts18-1737 packages/ui/src/i18n/locales/zh-TW.ts18-1642
Components access translations via the useI18n() composable (line 321):
Interpolation: Message keys support variable substitution:
Pluralization: Some keys support plural forms:
Sources: packages/ui/src/components/app-layout/PromptOptimizerApp.vue321-322 packages/ui/src/i18n/locales/en-US.ts56 packages/ui/src/i18n/locales/en-US.ts613 packages/ui/src/i18n/locales/en-US.ts917
The selected locale is persisted to storage via PreferenceService:
initializeI18nWithStorage() reads stored locale preference'en-US'Storage Key: The locale preference is stored under a specific key in PreferenceService (typically 'ui-language' or similar).
Sources: packages/ui/src/plugins/i18n.ts (referenced in packages/ui/src/components/app-layout/PromptOptimizerApp.vue294)
| Category | Line Range (en-US.ts) | Key Count | Example Keys |
|---|---|---|---|
common.* | 19-105 | 86 | loading, save, cancel, version, optimize |
nav.* | 109-124 | 15 | promptOptimizer, modelManager, history, favorites |
contextMode.* | 125-165 | 40+ | optimizationMode, user.label, system.tooltip |
favorites.* | 162-428 | 260+ | manager.title, dialog.createTitle, categoryManager.* |
promptOptimizer.* | 416-475 | 58 | title, optimize, optimizeModel, defaultOptimizationContext |
variables.* | 460-622 | 161 | management.*, editor.*, preview.*, importer.* |
conversation.* | 604-729 | 124 | title, addMessage, roles.*, templates.*, syncToTest |
modelManager.* | 723-891 | 167 | testConnection, apiUrl, advancedParameters.*, capabilities.* |
templateManager.* | 893-1024 | 130 | addTemplate, messageTemplates, migrationDescription |
test.* | 1014-1154 | 139 | variables.*, variableValueGeneration.*, layout.* |
toast.* | 1234-1331 | 96 | error.*, success.*, warning.*, info.* |
dataManager.* | 1335-1400 | 64 | export.*, import.*, contexts.*, storage.* |
params.* | 1391-1543 | 151 | temperature.*, top_p.*, max_tokens.*, logprobs.* |
contextEditor.* | 1544-1718 | 173 | contextVariables, toolsTab, importFormats.* |
Special Categories:
toast.* - Toast notification messages for success/error/warning feedbackparams.* - Model parameter descriptions (temperature, top_p, etc.) with technical documentationcontextEditor.* - Context editing UI with import/export format definitionsvariableDetection.* - Auto-complete hints and variable source labelsSources: packages/ui/src/i18n/locales/en-US.ts18-1707
The application uses Naive UI's theming system with six pre-configured themes. Theme state is managed through Pinia stores and persisted to storage.
Diagram: Theme Application and State Flow
Theme Application Flow:
useNaiveTheme() called when services availablePreferenceServiceNConfigProvider receives theme config via computed refs (lines 15-16)NGlobalStyle applies CSS variables to <body> element (line 206)Sources: packages/ui/src/components/app-layout/PromptOptimizerApp.vue15-16 packages/ui/src/components/app-layout/PromptOptimizerApp.vue206 packages/ui/src/components/app-layout/PromptOptimizerApp.vue284 packages/ui/src/components/app-layout/PromptOptimizerApp.vue537
Each theme in naiveThemeConfigs contains:
lightTheme or darkTheme from Naive UIExample Theme Definition (conceptual):
Sources: packages/ui/src/config/naive-theme.ts (referenced in packages/ui/src/components/ThemeToggleUI.vue34)
ThemeToggleUI dropdown and selects a themeuseNaiveTheme().changeTheme(themeId) is invokeduseGlobalSettings) updates current theme IDPreferenceServiceNConfigProvider receives new theme config via reactive refsNGlobalStyle injects updated CSS variables into <body>Sources: packages/ui/src/components/ThemeToggleUI.vue48-56 packages/ui/src/components/app-layout/PromptOptimizerApp.vue14-18 (NConfigProvider usage), packages/ui/src/components/app-layout/PromptOptimizerApp.vue206 (NGlobalStyle)
The ThemeToggleUI component provides a dropdown with:
max-md:hidden) to save spaceIcon Mappings:
| Theme ID | Icon | Color (when active) |
|---|---|---|
light | Sun | Yellow (#eab308) |
dark | Moon | Blue (#60a5fa) |
blue | Star | Blue (#2563eb) |
classic | Coffee mug | Beige (#b08968) |
green | Leaf | Green (#16a34a) |
purple | Sparkles | Purple (#9333ea) |
Sources: packages/ui/src/components/ThemeToggleUI.vue38-112
The selected theme is stored in PreferenceService under a key like 'ui-theme'. On application startup, initializeNaiveTheme() restores the saved theme:
naiveThemeConfigs'light' if invalid or missingSources: Referenced in packages/ui/src/composables/ui/useNaiveTheme.ts (not provided but imported in packages/ui/src/components/app-layout/PromptOptimizerApp.vue284)
The PromptOptimizerApp does not globally register Vue components. Instead, components are imported locally where needed. This approach:
Exception: Naive UI components (NButton, NCard, etc.) are imported individually from naive-ui package.
Sources: packages/ui/src/components/app-layout/PromptOptimizerApp.vue234-256 (component imports)
The application follows a multi-phase startup sequence with clear state gates:
Diagram: Initialization Phase Sequence
State Gates:
isInitializing (line 19) - Shows loading spinner until services createdservices !== null (line 23) - Prevents rendering if bootstrap failsrouteInitialized (line 479) - Gates route correction until GlobalSettings restoredisReady (line 26) - Final gate before full UI renderLoading UI States:
Critical Initialization Order:
PreferenceService required for locale persistenceSources: packages/ui/src/components/app-layout/PromptOptimizerApp.vue19-30 packages/ui/src/components/app-layout/PromptOptimizerApp.vue383 packages/ui/src/components/app-layout/PromptOptimizerApp.vue479 packages/ui/src/components/app-layout/PromptOptimizerApp.vue537-668
PromptOptimizerApp manages visibility of global modals and drawers:
| Modal/Drawer | Visibility Ref | Component | Purpose |
|---|---|---|---|
| Model Manager | modelManager.showConfig | ModelManagerUI | Configure text/image models |
| Template Manager | templateManagerState.showTemplates | TemplateManagerUI | Manage prompt templates |
| History Drawer | historyManager.showHistory | HistoryDrawerUI | View optimization history |
| Data Manager | showDataManager | DataManagerUI | Import/export application data |
| Favorite Manager | showFavoriteManager | FavoriteManagerUI | Manage favorite prompts |
| Variable Manager | showVariableManager | VariableManagerModal | Manage global variables |
| Tool Manager | showToolManager | ToolManagerModal | Configure tool definitions |
| Context Editor | showContextEditor | ContextEditor | Edit conversation context |
| Prompt Preview | showPreviewPanel | PromptPreviewPanel | Preview prompt with variables |
All modals use v-model:show bindings for visibility control and emit close events to parent.
Sources: packages/ui/src/components/app-layout/PromptOptimizerApp.vue73-204
The PromptOptimizerApp receives configuration through:
VITE_*)provide('appServices', servicesRef)Provided Context Keys:
appServices: Full AppServices object with core, ui, and storage propertiesrouter: Vue Router instance (implicitly via <RouterView>)i18n: vue-i18n instance (implicitly via plugin)Sources: packages/ui/src/components/app-layout/PromptOptimizerApp.vue435 (provide call), packages/ui/src/types/services.ts (AppServices type definition, referenced)
Refresh this wiki